Thursday, September 11, 2014

Apache CXF and JAXB to convert Date object to json custom formatted string

Sometimes your api requires that you print a custom formatted ui friendly date rather than a long timestamp. Following shows you how to create a adapter so your json model returned from the api contains custom formatted date for example.

1) first Maven you will need the following at least:
<dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
         <version>1.9.13</version>
         </dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-xc</artifactId>
            <version>1.9.13</version>
  </dependency>  
2) assuming you apache CXF config should look like so to add the JacksonJaxbJsonProvider, like so in your spring config file:

    <jaxrs:server id="someservice" address="/">
       <jaxrs:serviceBeans>
           <bean class="com.company.ListAPI" />          
       </jaxrs:serviceBeans>  
        <jaxrs:extensionMappings>
        <entry key="json" value="application/json"></entry>
           <entry key="xml" value="application/xml"></entry>
        </jaxrs:extensionMappings>
        <jaxrs:features>
             <cxf:logging/>
        </jaxrs:features>
        <jaxrs:providers>
    <ref bean="jsonProvider"/>
</jaxrs:providers>
        </jaxrs:server>
      <bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"/>


3) now annotate your model that you pass back in your api like so:

public class SomeModel {
       @XmlJavaTypeAdapter(StartDateAdapter.class)
protected Date startDate=new Date();
//other properties//getters/setters...
}

4) implement the adapter that converts between string and date:

    public class StartDateAdapter extends XmlAdapter<String, Date>{

@Override
public Date unmarshal(String value) throws Exception {
DateFormat date = new SimpleDateFormat("dd-MM-yyyy HH:mm");
       if (value == null || value.length() == 0) {
           return null;
       }
       Date d = null;

       try {
           d = date.parse(value);
       } catch (Exception e) {
           e.printStackTrace();
           return null;
       }
       return d;
}

@Override
public String marshal(Date value) throws Exception {
if (value == null) {
           return null;
       }
       DateFormat date = new SimpleDateFormat("dd-MM-yyyy HH:mm");
       return date.format(value.getTime());
}

}


Thats it!
now whenever you get the json or send the json in your API, like so in apache cxf endpoint, jaxb will will use your adapter to make your date look meanigful.

 @POST
@Path(value = "/start")
@Consumes(MediaType.APPLICATION_JSON)
public Response  startDeploys(
@RequestBody(required = true) SomeModel userModel) {
               Date userInputDate =usermodel.getStartDate();
                return Response.ok("Date you entered in the body of the post looks good..thanks").build();
       }


  @GET
@Path(value = "/list")
public Response  startDeploys(
@RequestBody(required = true) SomeModel userModel) {
             return Response.ok( new SomeModel () ).build();
       }






Monday, August 11, 2014

incompatible JPA spec

Sometimes you can get an error like so:

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/sprin
g/spring-orm.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: javax.persistence.spi.PersistenceUnitInfo.getValidationMod
e()Ljavax/persistence/ValidationMode;


It could also mean that the dependency you are including may be dependent on an incompatible dependency with your project.
for example..
you can do <exclusions> tag to not package the offending dependency in your war by doing something like this:

<dependency>
   <groupId>com.ibm.websphere</groupId>
   <artifactId>wxsutils</artifactId>
   <version>2.5.4-SNAPSHOT</version>
           <exclusions>
                 <exclusion>
                   <groupId>org.apache.geronimo.specs</groupId>
                   <artifactId>geronimo-jpa_3.0_spec</artifactId>
                </exclusion>
           </exclusions>
</dependency>