22/08/2019

[Spring] Schedule tasks

Scheduling execution of tasks in Spring is quite easy and requires just a couple annotations:

  • Annotate the application class with @EnableScheduling
  • Provide an @Component annotated class which includes the methods to be scheduled, each annotated with @Schedule 
The schedule itself can be passed as a property. 

[Maven] Generate Avro sources at compile time

If you are using Apache Avro in your project, you might want to automatize the sources generation step so that at every compile, the target classes are built from the Avro schema.

In Maven, this can be done with the avro-maven-plugin with a configuration as such:

 <project>  
   <modelVersion>4.0.0</modelVersion>  
   <groupId>com.blogspot.groglogs</groupId>  
   <artifactId>sample-avro-maven-pom</artifactId>  
   <version>1</version>  
   
   <dependencies>  
     <dependency>  
       <groupId>org.apache.avro</groupId>  
       <artifactId>avro</artifactId>  
     </dependency>  
   
     <!--   
     Use this for testing purposes only if you wish to manually generate the classes from Avro sources:  
   
     java -jar avro-tools.jar compile schema SCHEMA_FILE.avsc TARGET_DIRECTORY  
   
     See: https://avro.apache.org/docs/current/gettingstartedjava.html  
     <dependency>  
       <groupId>org.apache.avro</groupId>  
       <artifactId>avro-tools</artifactId>  
       <scope>provided</scope>  
     </dependency>  
     -->  
   </dependencies>  
   
   <build>  
     <plugins>  
       <plugin>  
         <groupId>org.apache.avro</groupId>  
         <artifactId>avro-maven-plugin</artifactId>  
         <executions>  
           <execution>  
             <phase>generate-sources</phase>  
             <goals>  
               <goal>schema</goal>  
             </goals>  
             <configuration>  
               <sourceDirectory>SOURCE_DIR</sourceDirectory>  
               <outputDirectory>DEST_DIR</outputDirectory>  
             </configuration>  
           </execution>  
         </executions>  
       </plugin>  
     </plugins>  
   </build>  
 </project>  


Remember that it is also possible to use avro-tools to manually generate sources from a schema.

[Java] Date and Time utilities

Since java 8 introduced the java.time package, a lot of useful objects and methods are now available without the need to import external libraries.

Here are some operations that might come in handy when dealing with LocalDate and LocalDateTime objects:

  • Convert String timezone (in format {Region}/{City} eg: "Europe/Rome") to ZoneOffset:
 public static ZoneOffset stringToZoneOffset(final String timezone){  
   final ZoneId zone = ZoneId.of(timezone);  
   return zone.getRules().getOffset(Instant.now());  
 }  

  • Retrieve the hours offset between UTC and a given timezone:
 public static int hoursOffsetFromUTC(final String timezone){  
   return ZoneId.of(timezone)  
              .getRules()  
              .getOffset(Instant.ofEpochMilli(1_498_329_000_000L))  
              .getTotalSeconds()/3600;  
 }  

  • Convert given time (in format HH:mm:ss) with specific timezone to UTC time:
 public static OffsetTime timeAndTimezoneAtUTC(final String time, final String timezone){  
   return LocalTime.parse(time, DateTimeFormatter.ISO_LOCAL_TIME)  
                .atOffset(stringToZoneOffset(timezone))  
                .withOffsetSameInstant(ZoneOffset.UTC);  
 }  

  • Convert date to epoch seconds (if we had a LocalDateTime, we wouldn't need to use atStartOfDay):
 public static Long localDateToEpoch(final LocalDate localDate){  
   return localDate.atStartOfDay(ZoneOffset.UTC).toEpochSecond();  
 }  

11/08/2019

[Linux] Text handling for counting and replacing words

Here is a list of handy commands for VI and SED to count and replace text in a file. For both editors the escape character is /:

VI:

- count total words:

 :%s/\i\+/&/gn    


- count occurrences of particular word:

 :%s/WORD/&/gn    



SED:

- copy all text from marker until end of file:

 sed -n -n '/MARKER/,$p' in >> out  


- replace all occurrences of SOURCE to TARGET with optional characters before SOURCE:

 sed -E 's/(OPTIONAL)?SOURCE/\1TARGET/g' in >> out  

27/04/2019

[Spring Boot] Configure CORS

CORS (Cross-origin resource sharing) is an important security aspect of modern web applications. To prevent malicious content from being pulled into your page, usually the source(s) of the content for it are restricted to prevent external domains from serving pieces of your final page.
This functionality goes along with CSRFX-Frame-Options, SessionPolicy and SecurityHeaders to provide a complete setup for your application.

All of this can be however very easily configured in Spring version 4+ (and therefore Spring Boot 2 as well) by providing a custom SecurityConfig (WebSecurityConfigurerAdapter) that will prevent Spring Boot from autoconfiguring the security with its own defaults.

Here is a sample implementation for Spring Boot 2 that completely disables (allows everything) CORS, it comes from this StackOverflow, slightly modified:

[Spring Boot] Upload file

In Spring Boot 2, your controller can expose a POST method to accept a file upload and return a JSON response simply as such:

 @RequestMapping(value="/upload", method=RequestMethod.POST, consumes = {"multipart/form-data"}, produces=MediaType.APPLICATION_JSON_VALUE)  
 @Transactional  
 public ResponseEntity<String> uploadFile(@ModelAttribute FileUploadRequest fileUploadRequest) {  
   
  fileUploadRequest.getFile(); //@TODO do something with your file  
   
  return new ResponseEntity<String>("{\"result\":\"success\"}", HttpStatus.OK);  
 }  
   
   
   
 @InitBinder  
 protected void initBinder(HttpServletRequest request,  
              ServletRequestDataBinder binder)   
 throws ServletException {  
  binder.registerCustomEditor(byte[].class,  
                new ByteArrayMultipartFileEditor());  
 }  


And the FileUploadRequest class looks something like this:

 @Accessors(chain = true)  
 @AllArgsConstructor  
 @NoArgsConstructor  
 public class FileUploadRequest {  
   private String fileName;  
   private byte[] file;  
 }  


With all the magic annotations coming from Lombok, Gradle configuration will look like this:

annotationProcessor "org.projectlombok:lombok:VERSION"
compileOnly "org.projectlombok:lombok:VERSION"

[Spring Boot] Download or display file in browser from controller

In Spring Boot 2, we can provide an endpoint that allows users to perform GET requests to download (or display) a file in their browsers as follows:

 @RequestMapping("/downloadFile/{fileId}")  
 public ResponseEntity<byte[]> downloadFile(@PathVariable("fileId") String fileId){  
  File file = null; //@TODO get your file from wherever using fileId or the logic you need  
   
  byte[] fileBytes = Files.readAllBytes(file.toPath()); //@TODO for example, but you might convert file to byte[] as you wish  
   
  HttpHeaders headers = new HttpHeaders();  
  headers.setContentType(MediaType.APPLICATION_PDF); //@TODO change accordingly!  
  headers.setContentDispositionFormData("attachment", file.getName()); //change to "inline" if you wish the browser to try do display it instead of downloading. WARNING: behaviour is browser dependent!  
  headers.setCacheControl("must-revalidate, post-check=0, pre-check=0"); //prevent caching  
  ResponseEntity<byte[]> response = new ResponseEntity<>(fileBytes, headers, HttpStatus.OK);  
  return response;  
 }  
   
   
   
 @InitBinder  
 protected void initBinder(HttpServletRequest request,  
              ServletRequestDataBinder binder)   
 throws ServletException {  
  binder.registerCustomEditor(byte[].class,  
                new ByteArrayMultipartFileEditor());  
 }