Wednesday, December 26, 2018

Pitfall when using hibernate + date in entity

It’s a frequently encountered pitfall when using hibernate, also has entity with properties type defined as java.util.Date. 

In short, although the entity’s property is defined as java.util.Date in entity class, but at runtime hibernate will never set it as java.util.Date, but java.sql.Timestamp!

Since java.util.Date is the parent class of java.sql.Timestamp, so in your code whenever treat this field as java.util.Date, there is no exeption at compilation or runtime. But the unexpected result often come when the eqals operation involved.

An instance of java.sql.Timestamp will NEVER equal to any instance of java.util.Date! (caused by Timestampl’s impl of equals method, see javadoc of Timestamp), even logically they represent the exactly time.

The following example shows you how this pitfall looks like.

Entity class

Suppose we have a entity class ‘User’.

@Entity
@Table(name = "user")
public class User {
    @Id
    private Long id;
    private String name;
    @Column(name = "changed_at")
    private Date changedAt;

    // setter getter omitted
}

There is a field “changedAt” defined as time java.util.Date.

Database

In database, we have following data

image


code to show the pitfall

Let’s run the following code.

        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date a = df.parse("2010-11-02 11:00:00");       // a is instance of Date
        Date b = userRepository.findById(id).get().getChangedAt();  // b is actually a instance of Timestamp

        System.out.println("a.getTime() == b.getTime() is " + (a.getTime() == b.getTime()));
        System.out.println("a.equals(b) is " + a.equals(b));
        System.out.println("b.equals(a) is " + b.equals(a));

Although the variable is also defined a ‘Date’ but thanks to hibernate,  at runtime it’s an instance of Timestamp

Then we have the following output

a.getTime() == b.getTime() is true
a.equals(b) is true
b.equals(a) is false

As you can see, even a and b represent the same logic time, the equals result are different.  You many wonder why b.equals (a) is false, here is the reason.

    public boolean equals(java.lang.Object ts) {
      if (ts instanceof Timestamp) {
        return this.equals((Timestamp)ts);
      } else {
        return false;
      }
    }

Above is the equals() impl of class java.sql.Timestamp. Caused by the instanceof check, a instance of Timestamp never equals to instance of Date.


Conclusion

  • When work with hibernate and entity with date, always remember they are not real ‘Date’, but ‘Timestamp’,
  • Always use Data instance’s equals() methods

Saturday, December 22, 2018

Several useful cases for maven plugin “dependency”

The maven dependency plugin is very handy when trying to deal with following questions:

  • What are the external artifacts involved in a maven project. (dependency:resolve)
  • Find out how an artifact is introduced into a project. (dependency:tree)
  • In a multi modules project, how these modules denpend on each other? (dependency:tree –Dincludes=com.mypackage.*)
  • Find out unnecessary dependencies in a maven project. (dependency:analyze)


To solve these puzzles, we need to know some typical usage of maven dependency plugin.

1. goal ‘resolve’

#list all dependencis
mvn dependency:resolve 

Output looks like below.

image

2. goal ‘tree’

# list dependencies tree. 
# can use –Dincludes=[groupId]:[artifactId]:[type]:[version], can use wildcard *

# e.g  -Dincludes=org.springframework*,org.apache*    # list only package from spring and apache.

mvn dependency:tree  -Dincludes=org.springframework*

Output looks like below.

image


3. goal ‘analyze’

# List possible inmproper dependency. 
# 1.avoid ‘Used undeclared dependencies`
# 2.'Unused declared dependencies` are not 100% reliable, cause of <provide> or <optional>
#    need to check manually

mvn dependency:analyze

Output looks like below.

image

In above screenshot there are several suspicious dependencis may not be used at all. Then use “dependency:tree –Dincludes= org.springframework.boot:spring-boot-starter-web” to see how this dependency is introduced to the project.

Sunday, March 12, 2017

How to security a website in public key infrastructure (PKI) – Basic Concept

Let’s suppose you are a owner of a website, which has domain name www.shengw.com

Here is the flow and it’s basic idea behind it.

image

 

CA’s role is to make sure the public key, PK1, that client used to to decode message is really belongs to www.shengw.com. Furthermore to prove any message succefully deocded by PK1 is really come from www.shengw.com's private key.

Client talks to www.shengw.com can be a browser or a Java application. In the last step what if the CA's public key is not known to the client (e.g  certificate file is not from a famous CA orgnization or even self-signed)?

  • If client is a browser, then install the CA’s root certification to the operating system’s trusted root certification authorities store.
  • If client is a java application, then  import the certificate from CA into application’s truststore jks file.

Saturday, March 11, 2017

Use Fiddler to debug https request from java application

Fiddler is a very handy tool for http related debug.  After starting, it automatically start to capture any http request go through system proxy. Also it by default listen to port 8888. For debug Java application, we stop the automatic capturing, only use the port 8888. 

image_thumb4

This articlae is for debug HTTPS  request from java application, if the java application send out HTTP request, please go to this article.

Target

You have a java application, which send https requestion out.  For debugging purpose, You want to find out what exactly be sent out as well as its response.

image

Solution

Different from http, proxy https request need more steps.

1. Get Fiddler Root Ceretificate file ( .cer file)

Open Fiddler, tools->Telerik Fiddler options

image

Choose HTTPS tab-> Export Root Certificate to Desktop.

image

Now you should be able to find the Certificate file “FiddlerRoot.cer” on desktop.  Let’s copy this file to directory C:/keystore.

image

2. Create truststore file from Fiddler Root Certificate (.cer file –> .jks file)

Use keytool to generate keystore file.

keytool -importcert -alias fiddler -file c:\keystore\FiddlerRoot.cer -keystore c:\keystore\fiddler_keystore.jks -storepass abcd1234

image

Now we have the fidder_keystore.jks file. From command line you can also find the storepass was set to “abcd1234”

3. Set proxy for JVM

Set http proxy for JVM either from java command or inside java code, here is a simple example by setting System properties in Java code.

package com.shengwang.demo;

import org.springframework.web.client.RestTemplate;

public class DemoMain {
  public static void main(String[] args) {
    enableHttpsProxy();
    RestTemplate restTemplate = new RestTemplate();
    String text = restTemplate.getForObject("https://www.facebook.com/", String.class);
    System.out.println(text);
  }

  private static void enableHttpsProxy() {
    System.setProperty("https.proxyHost", "127.0.0.1");
    System.setProperty("https.proxyPort", "8888");
  }
}

At the beginning of the code, we set proxy for https for JVM, then we try to access facebook by https.

4. Use the truststore file when running your Java application

If directly run the previous DemoMain class, you will get a Exception during the SSL handshaking, complain unable to find a validate certificate. So we need to run the DemoMain class with following JVM options:

-Djavax.net.ssl.trustStore=c:/keystore/fiddler_keystore.jks -Djavax.net.ssl.trustStorePassword=abcd1234

These 2 options tell JVM where to find the keystore file and the corresponding password to use the keystore. After you run the DemoMain with above options, we should be able to see the https request and its response from fiddler UI. Both request and response are decoded, so it’s very helpful during development.

image

Use Fidder to debug http request from java application

Fiddler is a very handy tool for http related debug.  After starting, it automatically start to capture any http request go through system proxy. Also it by default listen to port 8888. For debug Java application, we stop the automatic capturing, only use the port 8888.  

image

This articlae is for debug HTTP  request from java application, if the java application send out HTTPS request, please go to this article

Target:

You have a java application, which send http requestion out.  For debugging purpose, You want to find out what exactly be sent out as well as its response.

image

Solution:

Set http proxy for JVM either from java command or inside java code, here is a simple example by setting System properties in Java code.

package com.shengwang.demo;

import org.springframework.web.client.RestTemplate;

public class DemoMain {
  public static void main(String[] args) {
  
    enableHttpProxy(); // set system properties for http proxy
	
    RestTemplate restTemplate = new RestTemplate();
    String text = restTemplate.getForObject("http://www.bbc.com/", String.class);
    System.out.println(text);
  }


  public static void enableHttpProxy() {
    System.setProperty("http.proxyHost", "127.0.0.1");
    System.setProperty("http.proxyPort", "8888");
  }
}

This simple code just try to access www.bbc.com. After running it, we should be able to see the Http request and response from fiddler like below.

image

Spring RestTemplate useful hints

RestTemplate a widely used client tool from Spring framework. Here are some useful hints when using Spring RestTemplate.

  • How to use basic authentication with RestTemplate?
  • How to add arbitrary Http header, e.g.”Content-Type”, “Accept”, with RestTemplate?
  • How to bypass(not solve) Https error “java.security.cert.CertificateException: No name matching <some url> found”?

1. Basic authentication for RestTemplate

  RestTemplate restTemplate = new RestTemplate();

  // set username/password for http basic authentication
  restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("myUserName","myPassword"));

  // use restTemplate to send requst
  // .....

2. Add  arbitrary http header for RestTemplate

Like above for adding basic authentication, this time need your own ClientHttpRequestInterceptor implementation. (BasicAuhorizationInterceptor for basic authentication is already predefined in spring). 

  RestTemplate restTemplate = new RestTemplate();

  // set content-type=application/json http header
  restTemplate.getInterceptors().add(new ClientHttpRequestInterceptor() {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
      request.getHeaders().add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED.toString());
      return execution.execute(request, body);
    }
  });
		
  // use restTemplate to send requst
  // .....

For java8 +, using lamda can make it look more neat.  Functionally they are equivalent.

  RestTemplate restTemplate = new RestTemplate();

  // set content-type=application/json http header, use lamda 
  restTemplate.getInterceptors().add((request, body, execution) -> {
    request.getHeaders().add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED.toString());
    return execution.execute(request, body);
  });
		
  // use restTemplate to send requst
  // .....

Above example add content-type to http header, it can be used to add anything you like to http header.

3. Bypass Https error “java.security.cert.CertificateException: No name matching <some url> found”

When use RestTemplate to access resource with protocol https, it may has the exception complain something like “java.security.cert.CertificateException: No name matching <some url> found”. This is because the java applicatoin doesn’t has the right certification in its keystore.  As a developer you probably don’t want to get blocked when someone is working on the CA procedure.  You can continue by ignore this SSL host verification like below.  But this is only a temporary solution, should not be used on any production environment.

@Configuration
public class ByPassSSLVerificationConfig {
  // This RestTemplate actually ignore the SSL hostname verification
  @Bean
  public RestTemplate getRestTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
    TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
    HostnameVerifier allPassVerifier = (String s, SSLSession sslSession) -> true;  // ignore hostnaem checking

    SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
        .loadTrustMaterial(null, acceptingTrustStrategy).build(); // keystore is null, not keystore is used at all

    SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, allPassVerifier);
    CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();

    requestFactory.setHttpClient(httpClient);
    return new RestTemplate(requestFactory);
  }
}

Then inject your own RestTemplate bean and send https requests, the Exception will gone. But again this is only a bypass, not a final solution for this Exception.

Friday, August 19, 2016

Jersey in spring boot – Hello world example

Simply speaking:

JAX-RS, namely Java API for RESTful Service,  is from JSR 311 (obsolete) and JSR 339 (download here).

Jersey is an reference implementation of JAX-RS.

Spring boot sure can implement REST service without Jersey by using the controller way (@RestConroller). Also, jersey can be chosen for exposing the RESTful services.

This is a hello world level example of using Jersey with spring boot to provide RESTful services.

0. what you need

In this demo, following are used:

  • java 8
  • maven 3.2
  • spring boot 1.4.0.RELEASE

Jersey is included in spring boot release.

1. Maven pom.xml

Only one dependency is needed.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.shengwang.demo</groupId>
  <artifactId>rest-versioning</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>

  <name>rest-versioning</name>
  <description>Demo project for spring boot jersey rest</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.0.RELEASE</version>
    <relativePath/>
  </parent>

  <properties>
    <java.version>1.8</java.version>
  </properties>

  <dependencies>

    <dependency>
	  <!-- only dependency needed -->
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jersey</artifactId>
    </dependency>

  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

2. Java classes

In this hello world example, there are 5 classes totally.

  • Main class
  • POJO model class
  • Service
  • Jersey configuration
  • Endpoint

They will be shown one by one. The Jersey configuration and Endpoint class are more interesting, but for the completion for the demo, all classes are listed below.

2.1 Main class

This class is just a trival main class from spring boot.

package com.shengwang.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootJerseyApplication {

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

2.2.  POJO model

For demo usage. A model class is created. It’s just a POJO.

package com.shengwang.demo.model;

public class User {

  private String name;
  private int age;

  public User(String name, int age) {
    this.name = name;
    this.age = age;
  }
  
  // setter, getter ignored
}

2.3 Service class

A demo class just return a User object by a userId.

package com.shengwang.demo.service;

import com.shengwang.demo.model.User;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserService {
  private Map<String,User> users;

  @PostConstruct
  private void loadUser() {
    users = new HashMap<>();
    users.put("1",new User("Tom",20));
    users.put("2",new User("Jerry",19));
  }

  public User findById(String id) {
    return users.get(id);
  }
}

2.4 Jersey configuration

package com.shengwang.demo;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Component
@ApplicationPath("/v1")
public class JerseyConfig extends ResourceConfig {

  @Autowired
  public JerseyConfig(ObjectMapper objectMapper) {
    // register endpoints
    packages("com.shengwang.demo");
    // register jackson for json 
    register(new ObjectMapperContextResolver(objectMapper));
  }

  @Provider
  public static class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {

    private final ObjectMapper mapper;

    public ObjectMapperContextResolver(ObjectMapper mapper) {
      this.mapper = mapper;
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
      return mapper;
    }
  }
}

The JerseyConfig extends from jersey ResourceConfig, just register the endpoints and jackson for json.

2.5 Endpoint

Just like the spring controller, the jersey endpoint provides the URL mapping.

package com.shengwang.demo.endpoint;

import com.shengwang.demo.model.User;
import com.shengwang.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;


@Component
@Path("/users")
public class DemoEndpoint {

  @Autowired
  private UserService userService;

  @GET
  @Path("/{id}")
  @Produces(MediaType.APPLICATION_JSON)
  public User getEventVersion1(@PathParam("id") String id) {
    return userService.findById(id);
  }
}

Now everything is ready, the whole project looks like below.

Capture

3. Run it

Start the spring boot application from your IDE, and access the url from a brower. Here is the json result you get:

image

Powered by Blogger.

About The Author

My Photo
Has been a senior software developer, project manager for 10+ years. Dedicate himself to Alcatel-Lucent and China Telecom for delivering software solutions.

Pages

Unordered List