Over a million developers have joined DZone.

Oracle WebLogic 12.1.2 Now With EclipseLink MOXy JSON-Binding

· Integration Zone

Learn how API management supports better integration in Achieving Enterprise Agility with Microservices and API Management, brought to you in partnership with 3scale

Oracle WebLogic 12.1.2 is now available.  WebLogic 12.1.2 contains EclipseLink 2.4.2, this means that for the first time EclipseLink MOXy's JSON-binding is available in WebLogic out of the box.  I will demonstrate the benefits of using MOXy for JSON-binding with an example.
Java Model

Below is the Java model we will use for this post.  The same metadata will be used to customize the XML and JSON produced by our JAX-RS service.  The get/set methods have been omitted to save space.

Customer 

Below is a simple representation of a customer.  I have annotated a couple of the fields with MOXy's @XmlPath extension (see:  XPath Based Mapping) to demonstrate where MOXy is really being used.

package org.example.model;
 
import java.util.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
 
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
 
    @XmlAttribute(name="id")
    private int identifier;
    
    @XmlPath("personalInfo/firstName/text()")
    private String firstName;
     
    @XmlPath("personalInfo/lastName/text()")
    @XmlElement(nillable=true)
    private String lastName;
 
    @XmlElementWrapper
    @XmlElement(name="phoneNumber")
    private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
 
}

PhoneNumber 

We will map the PhoneNumber class to a complex type with simple content (see:  JAXB and Complex Types with Simple Content) to see the impact on JSON-binding.

package org.example.model;
 
import javax.xml.bind.annotation.*;
 
@XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {
 
    @XmlAttribute
    private String type;
     
    @XmlValue
    private String value;
 
}

package-info 

We will leverage the package level @XmlSchema annotation to namespace qualify the resulting XML (see: JAXB & Namespaces) so that we can see the impact on the JSON representation.

@XmlSchema(
    namespace="http://www.example.org/model",
    elementFormDefault=XmlNsForm.QUALIFIED)
package org.example.model;
 
import javax.xml.bind.annotation.*;

RESTful Service

CustomerResource 

Normally a real service will be backed by JPA to do persistence operations (see:  Creating a RESTful Web Service - Part 4/5). But for this post I will use a "Hello World" style service that returns a Customer based on an ID as XML and JSON to illustrate some points about binding.

package org.example.service;
 
import javax.ejb.*;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import org.example.model.*;
 
@Stateless
@LocalBean
@Path("/customers")
public class CustomerResource {
 
    @GET
    @Produces({
        MediaType.APPLICATION_XML,
        MediaType.APPLICATION_JSON
    })
    @Path("{id}")
    public Customer read(@PathParam("id") int id) {
        Customer customer = new Customer();
        customer.setId(id);
        customer.setFirstName("Jane");
        customer.setLastName(null);
         
        PhoneNumber pn = new PhoneNumber();
        pn.setType("work");
        pn.setValue("5551111");
        customer.getPhoneNumbers().add(pn);
         
        return customer;
     }
 
}

CustomerApplication 

MOXy is configured as the JSON-binding provider using the MOXyJsonProvider class via a JAX-RS Application class (see: MOXy as your JAX-RS JSON Provider - MOXyJsonProvider).  MOXyJsonProvider offers different settings you can use to customize the JSON representation.  In this example we will leverage the wrapperAsArrayName property to clean up the representation of collections (see:  Binding to JSON & XML - Handling Collections).

package org.example.service;
 
import java.util.*;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
  
@ApplicationPath("rest/*")
public class CustomerApplication  extends Application {
 
    @Override
    public Set<Class<?>> getClasses() {
        HashSet<Class<?>> set = new HashSet<Class<?>>(1);
        set.add(CustomerResource.class);
        return set;
    }
  
    @Override
    public Set<Object> getSingletons() {
        MOXyJsonProvider moxyJsonProvider = new MOXyJsonProvider();
        moxyJsonProvider.setWrapperAsArrayName(true);
  
        HashSet<Object> set = new HashSet<Object>(1);
        set.add(moxyJsonProvider);
        return set;
    }
 
}

Output

We will examine the output we get from calling our service with the following URL using the application/xml and application/json media types.

http://localhost:7001/CustomerResource/rest/customers/1

XML

Below is a sample of the XML output.  It isn't a surprise as it exactly matches the JAXB and MOXy metadata that we applied to our model.

<?xml version="1.0" encoding="UTF-8"?>
<customer
    xmlns="http://www.example.org/model" id="1">
    <personalInfo>
        <firstName>Jane</firstName>
        <lastName
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
    </personalInfo>
    <phoneNumbers>
        <phoneNumber type="work">5551111</phoneNumber>
    </phoneNumbers>
</customer>

Note the following XML specific things about this output.

  1. There is a root element (line 2).
  2. The XML is namespace qualified. (line 3).
  3. There are XML attributes (lines 3 & 10).
  4. The id attribute contains a int value (line 3).
  5. The xsi:nil attribute is used to indicate that the lastName element contains a null value. (lines 6 & 7).
  6. There are a collection of phoneNumber elements with a grouping element called phoneNumbers (lines 9-11).

JSON
Below is the JSON response when MOXy's JSON-binding is used by leveraging MOXyJsonProvider.  It was produced using the exact same metadata as the XML representation, but all the XML specific items are gone and JSON specific items are used instead.
{
    "id": 1,
    "personalInfo": {
        "firstName": "Jane",
        "lastName": null
    },
    "phoneNumbers": [
        {
            "type": "work",
            "value": "5551111"
        }
    ]
}

Now lets compare the JSON output with what WebLogic would have produced by default.  By default WebLogic uses its JAXB implementation with an intermediate library to convert XML events to/from JSON.  Since MOXy is the default JAXB implementation in WebLogic the @XmlPath annotation is applied, but we don't get any of the other benefits from MOXy's JSON-binding.

{
    "@id": "1",
    "personalInfo": {
        "firstName": "Jane",
        "lastName": {
            "@nil": "true"
        }
    },
    "phoneNumbers": {
        "phoneNumber": {
            "@type": "work",
            "$": "5551111"
        }
    }
}

Below are some of the problems that we see with the default representation that weren't present when we used MOXy's JSON-binding.  They are all due to the XML representation leaking into the JSON representation.

  1. Keys that correspond to properties mapped with @XmlAttribute are prefixed with @ (lines 2 & 11).
  2. The int value for the id property is incorrectly written as a JSON string (line 2).
  3. JSON representation of null is not used for the lastName key (lines 5-7).
  4. Our List of PhoneNumber objects were not marshalled correctly as a JSON array of size 1 (lines 10-13).
  5. Our phoneNumbers property will map to a JSON key of phoneNumber instead of phoneNumbers (line 10).

Unleash the power of your APIs with future-proof API management - Create your account and start your free trial today, brought to you in partnership with 3scale.

Topics:

Published at DZone with permission of Blaise Doughan, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}