Working with stateless session in hibernate and jpa

When doing heavy read-only operations in with the database it can be a good idea to take advantage of using Hibernate's Stateless Session

As it name indicates this session does not keep state of the entities that it retrieves from the database and so it bypasses the L1 and L2 cache

This can have significant performance impact on heavy DBA read operations (since the state of the entities is not bet tracked)



@Component
@Scope("prototype")
public class SomeJpaService {

public static final int SCROLL_STEP = 1000;

     @PersistenceContext
     private EntityManager entityManager;


    
     public void doInStatelessSession(){

       LOGGER.info("ABOUT to perform Heavy read operation on DB");

       StatelessSession statelessSession = entityManager.unwrap(Session.class).getSessionFactory().openStatelessSession();

        try (ScrollableResults r = statelessSession
                .createQuery("SELECT c FROM Order c")
                .setReadOnly(true)
                .setCacheable(false)
                .scroll()) {// create the scrollable results with a try/close resources block

            while (r.scroll(SCROLL_STEP)) {
                 Order o = (Order) r.get(0);
                //perform some operation on object
              
            }
        }      



        LOGGER.info("FINISHED heavy read operation");

        statelessSession.close();
   }


}

There's however a few caveats with this approach :

  • Collections cannot be fetched on stateless sessions
  • Because of the stateless nature of the session this can only be used on read-only operations

Serving angular2 content from Spring Boot application

Recently I had to ship an Angular2/Angular4 application within a Spring boot WAR packaged application and I was having some issues when dealing with the the urls in the angular routes, since it goes through the DispatcherServlet I was getting 404 all over the place

There are a few ways to handle this, below is my preferred solution :


@Controller
public class Angular2ViewController {


    @RequestMapping({"/books", "/login", "/admin", "/logout", "/configure"})
    public String index() {
        return "forward:/index.html";
    }

}

There you go, as easy as that

The inconvenience about this solution is that you have to maintain a set of urls in your controller also

Editable combobox in HTML5 and bootstrap

Creating an editable combobox in HTML5

Recently while reading the HTML5 specification I found out a new cool feature called datalist element


Which basically allows you to create an editable select form element by providing a list of possible values to an input whilst also allowing for new values to be provided (think of it as a basic auto-complete field)

Below is an example of how to implement this :




  
  
  


Note that this is also compatible with Bootstrap 4 and 3

Custom converter for Mongodb and Spring Data for BigDecimal type

Recently I found that MongoDB does not support java's java.math.BigDecimal as you can read in the official spring data mongodb documentation

As it turns out java.math.BigDecimal will be converted to java.lang.String when saved to the database and parsed back to BigDecimal which in most cases I guess it's alright

However as I found out things get broken when trying to perform range queries on this field such as : $gte, $lte you will get inconsistent results since MongoDB sees this as a String

Luckily this can be easily fixed by creating 2 custom converters (one for each side), below is how I've done it :

1. Define custom converters by implementing the appropriate interface

import org.springframework.core.convert.converter.Converter;

import java.math.BigDecimal;

public class BigDecimalToDoubleConverter implements Converter<BigDecimal, Double> {

    @Override
    public Double convert(BigDecimal source) {
        return source.doubleValue();
    }
}

import org.springframework.core.convert.converter.Converter;

import java.math.BigDecimal;


public class DoubleToBigDecimalConverter implements Converter<Double, BigDecimal> {

    @Override
    public BigDecimal convert(Double source) {
        return new BigDecimal(source);
    }
}

2. Configure the MongoTemplate to use the custom converters



@Configuration
public class MongoDBConfig  {

   
     //MongoDB properties read from the application.yaml configuration file (to handle different profiles)
    @Value("${spring.data.mongodb.host}")
    private String mongoHost;

    @Value("${spring.data.mongodb.port}")
    private int mongoPort;

    @Value("${spring.data.mongodb.database}")
    private String mongoDatabase;

   
    @Bean
    public MongoTemplate mongoTemplate() throws Exception {

        MongoTemplate mongoTemplate = new MongoTemplate(mongo(), mongoDatabase);
        MappingMongoConverter mongoMapping = (MappingMongoConverter) mongoTemplate.getConverter();
        mongoMapping.setCustomConversions(customConversions()); // tell mongodb to use the custom converters
        mongoMapping.afterPropertiesSet();
        return mongoTemplate;

    }

    /**
    * Configure the MongoDB client
    * 
    **/
    @Bean
    public Mongo mongo() throws Exception {
        return new MongoClient(mongoHost, mongoPort);
    }


   /**
    * Returns the list of custom converters that will be used by the MongoDB template
    * 
    **/
    public CustomConversions customConversions() {
        return new CustomConversions(Arrays.asList(new DoubleToBigDecimalConverter(), new BigDecimalToDoubleConverter()));
    }
}


Please note that this is OK in most cases however please note that in some cases this conversion from BigDecimal to Double may lead to issues; more info : Oracle's official doc on floating point arithmetic

Angular2 prevent ngboopstrap dialogs to close when clicking outside

The default behaviour for bootstrap modal dialogs is to close when you click outside the dialog however this is not always the desired behaviour

When using Bootstrap 4 without the angular wrapper you need to add the data-backdrop='static' and data-keyboard="false" to the button in order to achieve this :


If you are using the angular wrapper for bootstrap (and assuming you have your project already configured you can achieve this like so :

export class MyComponent implements OnInit {

    constructor(private modalService: NgbModal) {}

     showDialog(): void {
         this.modalService.open(ModalDialog,{size: "lg",backdrop: 'static', keyboard: false});
    }
}


And simply calling the showDialog() method from your template should do the trick

Prevent OSX from idle sleep

There are several ways to prevent an OSX system to sleep when idle such as the caffeine application or changing the parameters in the System preferences

However there is an even easier way to accomplish this without installing any extra apps, just open a terminal window and run the following command :

pmset noidle

You should see the following output :

Preventing idle sleep (^C to exit)...

Your OSX should now stay awake whilst pmset is running

Spring boot and mongodb with geo-localisation queries 1/3

MongoDB offers a number of indexes and query mechanisms to handle geospatial information, below are some of the features offered by the database :

  • Surfaces
  • Location Data
  • Query Operations
  • Geospatial indexes
  • .....

More detailed information can be found at their website : MongoDB Geospatial queries

In this 3 part post we will be creating a sample REST API application using Spring Boot, Spring Data and MongoDB to determinate if a given "Interest Point" is within a certain distance of the provided coordinates

1. Setup

Before we start please ensure that you have a running MongoDB instance

So let's get things started, we will be using Gradle as our build tool for this project, if you're not familiar with this build tool you can read the documentation

Below is the build file used to build our project, there is some noise in here that is related to IDE support as well as a few things needed to deploy this application in heroku which can be avoided but I've chosen to leave here for the sake of completion, the most interesting parts for us are the dependencies



buildscript {
 ext {
  springBootVersion = '1.5.2.RELEASE'
 }
 repositories {
  mavenCentral()
 }
 dependencies {
  classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
 }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'




jar {
 baseName = 'spring_mongodb_geospatial_api'
 version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
 mavenCentral()
}

task stage {
    dependsOn build
}


task wrapper(type: Wrapper) {
    gradleVersion = '2.6'
}


task copyToLib(type: Copy) {
    into "$buildDir/lib"
    from(configurations.compile)
}

stage.dependsOn(copyToLib)

dependencies {
 compile('org.springframework.boot:spring-boot-starter-data-mongodb') {
  exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
 }
 compile('org.springframework.boot:spring-boot-starter-web') {
  exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
 }
 compile('org.springframework.boot:spring-boot-starter-actuator'){
  exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
 }

 compile('org.springframework.boot:spring-boot-starter-log4j')

 compileOnly ("org.projectlombok:lombok:1.16.14")

 testCompile('org.springframework.boot:spring-boot-starter-test'){
  exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
 }
}


eclipse {
 classpath {
   containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
   containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
 }
}


Let's configure our spring boot application with the base info for our application to run (default profile, MongoDB info, etc.):

spring:
    application:
        name: spring_mongodb_geospatial_api
    profiles:
      active: dev



---
spring:
  profiles: dev
  data:
    mongodb:
      host: localhost
      port: 27017
      repositories:
        enabled: true

Let's now configure our bootstrap class :


package com.ufasoli.tutorials.mongogeospatial.ws;

import com.fasterxml.jackson.databind.Module;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.geo.GeoJsonModule;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@Configuration
@EnableAsync
public class SpringMongoDBGeospatial {

     public static void main(String[] args) {
 SpringApplication.run(SpringMongoDBGeospatial.class, args);
     }

    //Register a custom Serializer/Deserializer for the geospatial information
    @Bean
    public Module registerGeoJsonModule(){
        return new GeoJsonModule();
    }
}

This is a pretty standard spring boot class except for the fact that we are declaring a custom JSON Serializer/Deserializer for handling geospatial information

Finally let's create our data model :

package com.ufasoli.tutorials.mongogeospatial.ws.model;

import lombok.Data;

import java.util.Date;


@Data
public class Updatable {

    private Date createdAt;
    private Date updatedAt;

    private Long updatedTimestamp;


}



package com.ufasoli.tutorials.mongogeospatial.ws.model;

import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
import org.springframework.data.mongodb.core.mapping.Document;

import java.io.Serializable;
import java.util.List;


@Document
@Data
public class InterestPoint extends Updatable implements Serializable {

    @Id
    private String uuid;

    @NotBlank
    private String displayName;

    private String displayPhoto;


    private List categories;

    @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
    private GeoJsonPoint location;


    public InterestPoint() {
    }

    public InterestPoint(String uuid, String displayName) {
        this.uuid = uuid;
        this.displayName = displayName;
    }

    public InterestPoint(String uuid, String displayName, GeoJsonPoint location) {
        this.uuid = uuid;
        this.displayName = displayName;
        this.location = location;
    }


}


package com.ufasoli.tutorials.mongogeospatial.ws.model;

import java.io.Serializable;

/**
 * Created by ufasoli
 */
public enum Category implements Serializable{

    CAFE,
    BAR,
    RESTAURANT,
    MUSEUM,
    BANK,
    METRO_STATION,
    BUS_STATION,
    THEATRE,
    HOTEL
}


And that it's for today, on the next part we will set up the web application and controllers

OSX show used ports or listening applications with their PID

On OSX you can display applications listening on a given port using the lsof the commands described below will show listening application...