193 Lotus blogs updated hourly. Who will post next? Home | Blogs | Search | About 
 
Latest 7 Posts
Re: Domino REST performance analysis
Thu, Mar 16th 2017 73
Domino & Java 1.8: Thank you, IBM!
Tue, Mar 14th 2017 21
Domin & REST: Debug your Plugin
Tue, Mar 7th 2017 11
Domino & REST: More about Jackson
Fri, Mar 3rd 2017 8
Domino & REST: Accessing Domino’s Environment / Check Authentication
Thu, Mar 2nd 2017 8
Domino & REST: Consuming JSON
Wed, Mar 1st 2017 11
Domino & REST: A basic Servlet
Tue, Feb 28th 2017 15
Top 10
Re: Domino REST performance analysis
Thu, Mar 16th 2017 73
Domino & Java 1.8: Thank you, IBM!
Tue, Mar 14th 2017 21
Domino & REST: A basic Servlet
Tue, Feb 28th 2017 15
Jackson: Skip Objects conditionally
Wed, Feb 8th 2017 12
Domino & REST: Consuming JSON
Wed, Mar 1st 2017 11
Domin & REST: Debug your Plugin
Tue, Mar 7th 2017 11
XPages: Running Google’s Chrome V8 Javascript Engine
Sun, Nov 9th 2014 10
Hardening SSH vs. Eclipse RSE
Tue, Jan 13th 2015 9
Testing XPages (2): BrowserMob Proxy
Thu, Sep 17th 2015 9
REST & Security: CSRF Attacks
Tue, Dec 30th 2014 8


Jackson: Skip Objects conditionally
Twitter Google+ Facebook LinkedIn Addthis Email Gmail Flipboard Reddit Tumblr WhatsApp StumbleUpon Yammer Evernote Delicious
Sven Hasselbach    

I had a simple problem when implementing this brilliant solution in one of my REST applications: As soon I was using @JsonAnyGetter / @JsonAnySetter and the HidableSerializer together, a NPE was thrown during serialization. The Problem occured in Jackson 1.9.13 and even 2.5.0, the latest version usable with the actual Domino JVM.

  • Stack Trace
org.codehaus.jackson.map.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: ch.hasselba.Test["[anySetter]"])
null
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)
    at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
at ch.hasselba.HidableSerializer.serialize(HidableSerializer.java:29)
    at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
    at org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2575)
    at org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2097)
    at ch.hasselba.Demo.main(Demo.java:54)
Caused by: java.lang.NullPointerException
    at org.codehaus.jackson.map.ser.std.MapSerializer.serializeFields(MapSerializer.java:243)
    at org.codehaus.jackson.map.ser.AnyGetterWriter.getAndSerialize(AnyGetterWriter.java:41)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:154)
    ... 7 more

After hours of investigation, a simple solution came up on SO: The default serializer must be resolved, and then the code will work. I just had to override resolve method of my HidableSerializer:

@Override
public void resolve(SerializerProvider serializerProvider) throws JsonMappingException {
    if(defaultSerializer instanceof ResolvableSerializer) {
         ((ResolvableSerializer)defaultSerializer).resolve(serializerProvider);
    }
}

Here is a complete working example:

 

  • The Demo Code
package ch.hasselba;

import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.introspect.BasicBeanDescription;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.map.ser.BeanSerializerModifier;

public class Demo {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        // register the module
        Version version = new Version(1, 0, 0, "SNAPSHOT");
        mapper.registerModule(new SimpleModule("HidableModule", version) {
            @Override
            public void setupModule(SetupContext context) {
                super.setupModule(context);
                context.addBeanSerializerModifier(new BeanSerializerModifier() {
                    @SuppressWarnings("unchecked")
                    @Override
                    public JsonSerializer<?> modifySerializer(SerializationConfig config, BasicBeanDescription desc,
                        JsonSerializer<?> serializer) {
                        if (IHidable.class.isAssignableFrom(desc.getBeanClass())) {
                            return new HidableSerializer<Object>((JsonSerializer<Object>) serializer);
                        }
                        return serializer;
                    }
                });
            }
        });

        // the data
        String content = "{ "foo": "bar" }";

        // build the Object
        Test test = null;
        try {
            test =  mapper.readValue(content, Test.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // and now convert it back to a String
        String data = null;
        try {
             data = mapper.writeValueAsString(test);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println( data );

    }

}

 

  • Test Class
package ch.hasselba;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.codehaus.jackson.annotate.JsonAnyGetter;
import org.codehaus.jackson.annotate.JsonAnySetter;

public class Test implements IHidable {

    private Map<String, Object> others = new ConcurrentHashMap<String, Object>();

    @JsonAnyGetter
    public Map<String, Object> getOthers() {
        return this.others;
    }

    @JsonAnySetter
    public void addOther(final String name, final Object value) {   
        this.others.put(name, value);
    }

    @Override
    public boolean isHidden() {
        return false;
    }

}

 

  • Hideable Serializer
package ch.hasselba;

import java.io.IOException;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

public class HidableSerializer<T> extends JsonSerializer<T> {

    private JsonSerializer<T> defaultSerializer;

    public HidableSerializer(JsonSerializer<T> serializer) {
        defaultSerializer = serializer;
    }

    @Override
    public void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException, JsonProcessingException {

        if( value instanceof IHidable ){
            IHidable hidableValue = (IHidable) value;
            if( hidableValue.isHidden() )
                return;
        }
        defaultSerializer.serialize(value, jgen, provider);
    }

   @Override
   public void resolve(SerializerProvider serializerProvider) throws JsonMappingException {
       if(defaultSerializer instanceof ResolvableSerializer) {
            ((ResolvableSerializer)defaultSerializer).resolve(serializerProvider);
       }
   }
}

 

  • IHidable Interface
package ch.hasselba;

public interface IHidable {
    boolean isHidden();
}


---------------------
http://hasselba.ch/blog/?p=2293
Feb 08, 2017
13 hits



Recent Blog Posts
73
Re: Domino REST performance analysis
Thu, Mar 16th 2017 8:51p   Sven Hasselbach
I have created a Quick-n-Dirty performance test for Csaba’s „10K record test“: Loading time 200 ms overall, 60 ms TTFB. Do you want to know how this works? Feel free to come to SNoUG next week or to Rudi’s EntwicklerCamp and join my sessions.
21
Domino & Java 1.8: Thank you, IBM!
Tue, Mar 14th 2017 1:16p   Sven Hasselbach
For years it was a lot of pain when developing for the Domino platform using Java 1.6 only. But now, Java 1.8 is available, and this allows to use the latest versions for a lot of libraries and development tools. After installing FP8 to the Client, Eclipse allowes to use the Domino JRE in a JavaSE-1.8 environment: This gives access to the latest M2Eclipse plugin (1.7.0). The old version problem when running with JRE 1.6… … is solved: Eclipse Updates? No problem, just do it! Latest
11
Domin & REST: Debug your Plugin
Tue, Mar 7th 2017 11:14a   Sven Hasselbach
When developing OSGi Plugins, you should have your own development server running on your local machine. Not only because of the faster deployment of changes (a new version of a plugin must always deployed with a HTTP restart), but because of the Java debugging posibilities: Only one Eclipse instance can connect to the JVM, and every request processed by the server will start the debugger. If multiple users a accessing the server while you are debugging, your Eclipse will try to debug every inco
8
Domino & REST: More about Jackson
Fri, Mar 3rd 2017 10:16a   Sven Hasselbach
When creating a REST API servlet, Jackson provides a huge list of possibilities to manipulate the JSON data, mostly using annotations. Let’s demonstrate some of them with this little class, which has only two properties: public class Demo { private String foo; private String bar; public String getFoo() { return foo; } public void setFoo(String foo) { this.foo = foo; } public String getBar() { return bar; } public void setBar(String bar) { this.bar = ba
8
Domino & REST: Accessing Domino’s Environment / Check Authentication
Thu, Mar 2nd 2017 11:00a   Sven Hasselbach
If we want to access Domino’s Environment, it is the ContextInfo class which gives us all we need. Everything you need to do to use the class is described in an earlier blog post. The class gives mainly access to the following methods: Method Description getDataDirectory() Path to notes data directory getEnvironmentString(String envName) Returns the environment variable getServerDatabase() The actual database as NAPI object, if any getServerVariable(String varName) Variables
11
Domino & REST: Consuming JSON
Wed, Mar 1st 2017 7:25a   Sven Hasselbach
Consuming JSON is as easy as pie: Just create a new method to the RestApiServlet,  add a @POST annotation, and declare the object you want to the parameters of the method:     @POST     @Path("/helloworld/")     @Consumes(MediaType.APPLICATION_JSON)     public Response postHelloWorld(HelloWorld helloWorld) {         return Response.ok(helloWorld, MediaType.APPLICATION_JSON).build();     } In this example we are using the same URI „/helloworld/„; because
15
Domino & REST: A basic Servlet
Tue, Feb 28th 2017 1:49p   Sven Hasselbach
To have a good starting point when creating RESTful applications on top of Domino, I have created a „Hello World“ example of a JEE Application, based on Apache Wink & Jackson 2.5.0. The Jackson AnnotaionProcessor is registered into Apache Wink application and is enabled by default, the JAXB processor is also included as the secondary AnnotationProcessor. The benefit of this is that only one global ObjectMapper instance is created and is reused, wich allows a better performance as
8
Domino & REST: Listeners for Initialization & Destroying of a Servlet
Mon, Feb 27th 2017 9:15a   Sven Hasselbach
If you need to know when your Servlet is initialized or destroyed, you can use a ServletContextListener in your application. First, create the class AppServletContextListener and implement the javax.servlet.ServletContextListener interface. This provides two methods for capturing the events: contextInitialized and contextDestroyed: package ch.hasselba.servlet; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class AppServletContextListener  
13
Jackson: Skip Objects conditionally
Wed, Feb 8th 2017 7:51a   Sven Hasselbach
I had a simple problem when implementing this brilliant solution in one of my REST applications: As soon I was using @JsonAnyGetter / @JsonAnySetter and the HidableSerializer together, a NPE was thrown during serialization. The Problem occured in Jackson 1.9.13 and even 2.5.0, the latest version usable with the actual Domino JVM. Stack Trace org.codehaus.jackson.map.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: ch.hasselba.Test["[anySetter]"]) null  
8
Entwicklercamp 2017: Meine Vorträge & Hands-On
Thu, Jan 19th 2017 7:51a   Sven Hasselbach
Dieses Jahr spreche ich wieder auf dem Entwicklercamp, und halte neben den Vorträgen auch noch eine Hands-On Session: Track 1 – Session 2: XPages erweitern und ausbauen – Ausgabe 2017 Im Laufe des Jahres 2016 kamen einige Themen hinzu, und dank FP8 wird es wohl auch einige Neuerungen geben, über die man mal reden müsste… Track 4 – Session 3: High-Performance REST Applications Hochperformante REST Schnittstellen entwickeln, die auf dem Domino Server laufen? Der Vor




Created and Maintained by Yancy Lent - About - Planet Lotus Blog - Advertising - Mobile Edition