Friday, February 12, 2016

Apache Commons ToStringBuilder

It's not always possible to override the toString method, but luckily the Apache guys have a fix for that! In Apache Commons Lang you can find a class named ToStringBuilder.  It can, using reflection, output the value of all attributes in a class, that might not have a useful toString method.
It offers quite a few ways of formatting the output and you can even make your own formatting style.
Below class does not override the toString method, but with ToStringBuilder it's possible to nicely print the values.

 package com.blogspot.jpdevelopment.example.tostring;  
   
 public class ToString {  
   
   private final String attributeOne;  
   private final String attributeAnother;  
   
   public ToString(String attributeOne, String attributeAnother) {  
     this.attributeOne = attributeOne;  
     this.attributeAnother = attributeAnother;  
   }  
 }  
   

Using ToStringBuilder, output will be like in the comments above each System.out line.
 ToString toString = new ToString("attributeOne", "attributeAnother");  
   
 // com.blogspot.jpdevelopment.example.tostring.ToString@31befd9f[attributeOne=attributeOne,attributeAnother=attributeAnother]  
 System.out.println("Default toString: " + ToStringBuilder.reflectionToString(toString));  
   
 // attributeOne,attributeAnother  
 System.out.println("Simple toString: " + ToStringBuilder.reflectionToString(toString, ToStringStyle.SIMPLE_STYLE));  
   
 // com.blogspot.jpdevelopment.example.tostring.ToString@31befd9f[  
 //    attributeOne=attributeOne  
 // attributeAnother=attributeAnother  
 // ]  
 System.out.println("Multi line toString: " + ToStringBuilder.reflectionToString(toString, ToStringStyle.MULTI_LINE_STYLE));  
   
 // ToString[attributeOne=attributeOne,attributeAnother=attributeAnother]  
 System.out.println("Short prefix toString: " + ToStringBuilder.reflectionToString(toString, ToStringStyle.SHORT_PREFIX_STYLE));  
   
 // com.blogspot.jpdevelopment.example.tostring.ToString@31befd9f[attributeOne,attributeAnother]  
 System.out.println("No field names toString: " + ToStringBuilder.reflectionToString(toString, ToStringStyle.NO_FIELD_NAMES_STYLE));  

To make you own style, simple make a class that extends ToStringStyle.
 public class MyToStringStyle extends ToStringStyle {  
   
   public MyToStringStyle() {  
     this.setUseClassName(true);  
     this.setUseIdentityHashCode(false);  
     this.setUseFieldNames(true);  
     this.setContentStart("[start]");  
     this.setFieldSeparator(",");  
     this.setFieldSeparatorAtStart(false);  
     this.setContentEnd("[end]");  
   }  
 }  

The output now looks like this.
 // Custom toString: com.blogspot.jpdevelopment.example.tostring.ToString[start]attributeOne=attributeOne,attributeAnother=attributeAnother[end]  
 System.out.println("Custom toString: " + ToStringBuilder.reflectionToString(toString, new MyToStringStyle()));  

Thursday, February 4, 2016

Mapping a list with no root element using Jersey and Moxy

Consider this piece of JSon code. To map this into a List of Strings is not always as easy it one might think.

 [  
   "ListElement1",  
   "ListElement2",  
   "ListElement3"  
 ]  
If you just do like below:
 ClientConfig clientConfig = new ClientConfig();  
 Client client = ClientBuilder.newClient(clientConfig);  
 WebTarget webTarget = client.target("http://localhost/service");  
 Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);  
    
 Response response = invocationBuilder.get();  
 List<String> owners = response.readEntity(ArrayList.class);  
You will get an error like this:
 org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=class java.util.ArrayList, genericType=class java.util.ArrayList.  
To solve the problem, use a GenericType.
 ClientConfig clientConfig = new ClientConfig();  
 Client client = ClientBuilder.newClient(clientConfig);  
 WebTarget webTarget = client.target("http://localhost/service");  
 Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);  
   
 Response response = invocationBuilder.get();  
 List<String> owners = response.readEntity(new GenericType<List<String>>() { });  
This should do the trick. It will work for Map's as well.