Pages

Saturday, 1 March 2014

Customization support in REST Proxy


Usecase:
Using customization in JDeveloper for a REST proxy.

Pre-requisites:
Use JDeveloper 12c version along with Integrated weblogic server.

A Brief Intro:
JAXB forms an integral part of REST based services.
Customization mainly gives the power to control the names of the package and class names generated by JAXB. There may be various reasons why you might want to use customization in your REST service, one of them being the package and classes generated by the JAXB compiler may not be meaningful.
In my case, on running a REST proxy, I was facing the unmarshall exception as below:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"something"). Expected elements are <...>,<...>
One solution to this problem is to associate name attribute with XmlRootElement. Although this approach does solve the problem, due to some constraints, I could not stick to using this. Also, as I wanted to explore on the customization front, I took up the customization approach.

Steps:
In this blog, I have used a simple app CustomizationSample.zip to demonstrate customization in REST proxy. This app contains a REST service in EmployeeService.java, whose methods we shall invoke using the REST proxy. The application zip also contains the customization file. However, you could create a customization file on your own and place it anywhere wirthin your file system.

The customization file customizationFile.xml is as below. The inline comments indicate what this file does.


<?xml version="1.0" encoding="UTF-8"?>
<!-- This is the customization file for the schema employee.xsd-->
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.0" 
schemaLocation="http://localhost:7101/CustomizationSample-Project1-context-root/resources/application.wadl/xsd0.xsd" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns="http://www.example.org">
   <!-- This tells JAXB that the classes generated by it must be placed 
                        in the package with name myCustomizedPack-->
    <jaxb:schemaBindings>
        <jaxb:package name="myCustomizedPack"/>
    </jaxb:schemaBindings>
    
   <!-- This tells JAXB that the class for 'employeeList' complexType 
                           must be generated with name AllEmps-->    
    
    <jaxb:bindings node="xsd:complexType[@name='employeeList']">
        <jaxb:class name="AllEmps" />
    </jaxb:bindings>
 
    <!-- This tells JAXB that the element with name 'name' must be 
                        replaced with empName in JAXB class-->    
   
    <jaxb:bindings node="//xsd:element[@name='name']">
        <jaxb:property name="empName" />
    </jaxb:bindings>
</jaxb:bindings>

The most important part in this file wrt proxy is the schemaLocation. You can observe that the schemaLocation in my case was  http://localhost:7101/CustomizationSample-Project1-context-root/resources/application.wadl/xsd0.xsd 
To get the location, run the service. Append the generated WADL URL with xsd0.xsd. This schema is generated automatically for you by JDevelopr. Use this schemaLocation in your customization file.





Now you are all set to use this customization file in the REST proxy.
Create a new custom application, say CustomizationProxy. Invoke the REST client wizard. In the 'Create REST Proxy Client' wizard, supply the WADL URL and click on Customization Files. 

Locate the customization file by clicking on Add File in the 'Customization Files' pop up. Finally, click on Finish in REST Proxy Client wizard.



You can now observe that the JAXB classes are generated according to the customization file. Instead of the default 'generated' package, the package 'myCustomizedPack' is created as mentioned in the customization file. 




To invoke the methods of the service, you can now write a main method as below:
  public static void main(String[] args) {
        Client client = Localhost_CustomizationSampleProject1ContextRootResources.createClient();
        Localhost_CustomizationSampleProject1ContextRootResources.Project1 localhost_customizationsampleproject1contextrootresourcesproject1 =
        Localhost_CustomizationSampleProject1ContextRootResources.project1(client);
        // add your code here
        AllEmps allEmps = localhost_customizationsampleproject1contextrootresourcesproject1.getAsAllEmps();
        System.out.println("Number of emps:"+allEmps.getLists().size());
        System.out.println("Emp1 Name:"+allEmps.getLists().get(0).getEmpName());
    }

Here, if you observe, AllEmps was the name we assigned for EmployeeList class. Had we not used customization, the structure of the proxy would look as shown below:



Here, we can see that by default JAXB has generated a package by name 'generated' and the class names have been picked from the class names of the service. In this case, the main method would have a body as shown: 

    public static void main(String[] args) {
        Client client = Localhost_CustomizationSampleProject1ContextRootResources.createClient();
        Localhost_CustomizationSampleProject1ContextRootResources.Project1 localhost_customizationsampleproject1contextrootresourcesproject1 =
            Localhost_CustomizationSampleProject1ContextRootResources.project1(client);
        // add your code here
        EmployeeList allEmps = localhost_customizationsampleproject1contextrootresourcesproject1.getAsEmployeeList();
        System.out.println("Number of emps:"+allEmps.getLists().size());
        System.out.println("Emp1 Name:"+allEmps.getLists().get(0).getName());
    }
Thus, to conclude, customization gives us the flexibility to name the packages, classes and elements within these classes as per our requirements.

No comments:

Post a Comment