templates.plugins.spincast-jackson-xml.spincast-jackson-xml.html Maven / Gradle / Ivy
Show all versions of spincast-website Show documentation
{#==========================================
Spincast Jackson XML plugin
==========================================#}
{% extends "../../layout.html" %}
{% block sectionClasses %}plugins plugins-spincast-jackson-xml{% endblock %}
{% block meta_title %}Plugins - Spincast Jackson XML{% endblock %}
{% block meta_description %}Spincast Jackson XML plugin provides XML functionalities using Jackson.{% endblock %}
{% block scripts %}
{% endblock %}
{% block body %}
    
    
     
        
             Spincast Jackson XML plugin
            
                
                 default
                
             
        
    
    
    
    
        
        
        
        
            
            
                
                    
                    Overview
                
                
                    The Spincast Jackson XML plugin provides XML functionalities
                     using Jackson. It contains an implementation
                    of the IXmlManager interface.
                
                
                    Most of the time, the IXmlManager interface is used directly from
                    the request context via the 
                    xml() method or indirectly via
                    some methods on the response() add-on. 
                
                    
                    For example:
                
                
                
                    
                        
                            {% verbatim %}
public class AppController {
    public void myHandler(IDefaultRequestContext context) {
        // Create a Json object from a XML String, using the "xml()" add-on
        IJsonObject jsonObj = context.xml().fromXml("<user></user>");
        // Send an object as XML, using the "response()" add-on
        context.response().sendXmlObj(jsonObj);
    }
}{% endverbatim %}
                        
                    
                
                
                    You can also directly inject the IXmlManager
                    instance where you need it in your application.
                
  
             
            
	        
                
                    
                    Installation
                
	            
	                If you use the spincast-default artifact, this plugin is already installed so
	                you have nothing more to do!
	            
	            
                    
	                If you start from scratch using the spincast-core artifact, you can use the
	                plugin by adding this artifact to your project:
	                
	                    
	                        
<dependency>
    <groupId>org.spincast</groupId>
    <artifactId>spincast-plugins-jackson-xml</artifactId>
    <version>{{spincastCurrrentVersion}}</version>
</dependency> 
	                    
	                  
	            
	            
	                
	                You then install the plugin's Guice module, by passing it to the Guice.createInjector(...) method:
	                
	                    
	                        
Injector guice = Guice.createInjector(
        new SpincastCoreGuiceModule(args),
        new SpincastJacksonXmlPluginGuiceModule(IAppRequestContext.class, 
                                                IAppWebsocketContext.class)
        // other modules...
        ); 
	                    
	                   
	            
	            
	                ... or by using the install(...) method from your custom Guice module:
	                
	                    
	                        
public class AppModule extends SpincastCoreGuiceModule {
    @Override
    protected void configure() {
        super.configure();
        install(new SpincastJacksonXmlPluginGuiceModule(getRequestContextType(), 
                                                        getWebsocketContextType()));
        // other modules...
    }
    
    // ...
} 
	                    
	                   
	            
             
            
            
                
                    
                    The IXmlManager interface
                
                
                
 
                
                
                    
                        
 Methods :
                        
   
   
   
   
- 
    
String toXml(Object obj)
    
        Converts an object to XML.
If the object to convert is a IJsonObject, its elements
 of type "IJsonArray" will have a "isArray='true'" attribute
 added. This way, the XML can be deserialized back to a
 IJsonObject correctly.
    
 
- 
    
String toXml(Object obj, boolean pretty)
    
        Converts an object to XML.
        
    
 
- 
    
IJsonObject fromXml(String xml)
    
        Deserializes a XML to an IJsonObject. This
 will correctly manage the XML generated by
 toXml(), arrays included.
    
 
- 
    
IJsonArray fromXmlToJsonArray(String xml)
    
        Deserializes a XML to an IJsonArray. This
 will correctly manage the XML generated by
 toXml(), arrays included.
    
 
- 
    
<T> T fromXml(String xml, Class<T> clazz)
    
        Deserializes a XML to the given Class.
Be aware that if you use a default Type like
Map<String, Object>, the arrays will probably
 won't be deserialized correctly. Use the
 version returning a IJsonObject to get the
 arrays to work out of the box!
    
 
- 
    
<T> T fromXmlToType(String xml, Type type)
    
        Deserializes a XML to the given Type.
Be aware that if you use a default Type like
Map<String, Object>, the arrays will probably
 won't be deserialized correctly. Use the
 version returning a IJsonObject to get the
 arrays to work out of the box!
    
 
- 
    
<T> T fromXmlInputStream(InputStream inputStream, Class<T> clazz)
    
        Deserializes a XML inputstream to the given Type.
Be aware that if you use a default Type like
Map<String, Object>, the arrays will probably
 won't be deserialized correctly. Use the
 version returning a IJsonObject to get the
 arrays to work out of the box!
    
 
                        
                    
                
             
            
            
                
                    
                    Main configurations
                
                
                    You can bind a ISpincastXmlManagerConfig implementation to tweak
                     the default configurations
                    used by the components this plugin provides. By default, the
                    SpincastXmlManagerConfigDefault class is used as the implementation.
                
 
                
                
                    
                        
                            - 
                                
int getPrettyPrinterIndentationSpaceNumber()
                                
                                    The number of spaces to used to indent generated XML when
                                    pretty print is used.
                                    
                                    Defaults to 4 spaces.
                                
                             
                            - 
                                
String getPrettyPrinterNewlineChars()
                                
                                    The newline character(s) to use for generated XML when
                                    pretty print is used.
                                    
                                    Defaults to \n, wathever the platform the application is running on.
                                
                             
                            
                        
                    
                
             
           
            
                
                    
                    (de)serialization configurations
                
                
                    Jackson allows some configuration when serializing and deserializing an object.
                
 
                
                    Most of those configurations
                    are defined using annotations.
                    You can annotate the objects directly, or you can use mix-ins.
                
                
                
                    
                        
                            
                             Annotating the objects :
                        
   
                    
                    
                    
                        If you don't minds annotating your objects with Jackson specific annotations,
                        this is maybe the simplest thing to do. For example, let's say you have a User
                        class that has two fields, name and title, and you don't want 
                        to keep the title field when you 
                        serialize an instance of this class:
                    
 
                    
                        
                            
                                
public class User implements IUser {
    private String name;
    private String title;
    @Override
    public String getName() {
        return this.name;
    }
    @Override
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String getTitle() {
        return this.title;
    }
    @Override
    public void setTitle(String title) {
        this.title = title;
    }
} 
                            
                           
                    
                    
                        To ignore the title field to be included during the serialization, you can simply
                        annotate the getTitle() method with
                        @JsonIgnore (yes, you use the same annotations than the ones for Json mix-ins):
                        
                            
                                
public class User implements IUser {
    private String name;
    private String title;
    @Override
    public String getName() {
        return this.name;
    }
    @Override
    public void setName(String name) {
        this.name = name;
    }
    @Override
    @JsonIgnore
    public String getTitle() {
        return this.title;
    }
    @Override
    public void setTitle(String title) {
        this.title = title;
    }
} 
                            
                           
                    
                    
                    If you serialize an instance of this class using the XML Manager,
                    only the name property would be kept:
                        
                            
                                
IUser user = new User();
user.setName("Stromgol");
user.setTitle("alien");
String xml = getXmlManager().toXml(user);
assertNotNull(xml);
assertEquals("<User><name>Stromgol</name></User>", xml); 
                            
                           
                    
   
                
                
                
                    
                        
                            
                             Using mix-ins:
                        
   
                    
                    
                    
                        Many developers (us included) don't like to pollute their model classes
                        with too many annotations. Lucky us, Jackson provides a way to configure
                        objects from the outside, without annotating the objects directly, by using what is called 
                        mix-ins annotations.
                    
                    
                        Let's start with the same User class, without any Jackson annotations:
                    
                    
                        
                            
                                
public class User implements IUser {
    private String name;
    private String title;
    @Override
    public String getName() {
        return this.name;
    }
    @Override
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String getTitle() {
        return this.title;
    }
    @Override
    public void setTitle(String title) {
        this.title = title;
    }
} 
                            
                           
                    
                    
                    
                        To use XML mix-ins in a Spincast application,
                        you first need to create the mix-in abstract class. Interfaces work too, but
                        only to annotate methods, not fields.
                    
                    
                        An example mix-in for our IUser objects:
                        
                            
                                
public abstract class IUserMixin implements IUser {
    // Ignore this property!
    @Override
    @JsonIgnore
    public abstract String getTitle();
} 
                            
                           
                    
                    
                        As you can see, a mix-in extends the class/interface to configure, and adds
                        the Jackson annotations on the overriding fields or methods declarations.
                    
                    
                        Once the mix-in is defined, you have to register it, in your custom
                        Guice module:
                    
                    
                        
                            
                                
public class AppModule extends SpincastDefaultGuiceModule {
    public AppModule(String[] mainArgs) {
        super(mainArgs);
    }
    @Override
    protected void configure() {
        super.configure();
        bindXmlMixins();
        
        //...
    }
    protected void bindXmlMixins() {
        Multibinder<IXmlMixinInfo> xmlMixinsBinder = Multibinder.newSetBinder(binder(), IXmlMixinInfo.class);
        xmlMixinsBinder.addBinding().toInstance(new XmlMixinInfo(IUser.class, IUserMixin.class));
    }
} 
                            
                            
                                Explanation :
                                
                                    - 
                                        18 : A 
                                        multibinder is used
                                        to collect the various mix-ins to register. The advantage of a multibinder
                                        is that it allows to register mix-ins from any Guice module. For example, some
                                        plugins may want to register their mix-ins, and you may want to register your custom ones.
                                    
 
                                    - 
                                        19 : We register our mix-in, by binding a
                                        
XmlMixinInfo instance, which specifies the class to configure, and the 
                                        class of the mix-in used to configure it.
                                     
                                
                             
                                        
                           
                     
                    
                        With this in place, Spincast will automatically configure Jackson so it uses your mix-ins, and 
                        you would have the exact same result than annotating the User
                        class directly:
                        
                            
                                
IUser user = new User();
user.setName("Stromgol");
user.setTitle("alien");
String xml = getXmlManager().toXml(user);
assertNotNull(xml);
assertEquals("<User><name>Stromgol</name></User>", xml); 
                            
                           
                     
                    
                 
             
        
    
    
 
{% endblock %}    
 Spincast Jackson XML