28 September 2007

Using JAXB 2.0 with OC4J 10.1.3.x

OC4J 10.1.3.x provides a JAXB 1.0 implementation as part of its standard runtime. If you want to use JAXB 2.x then its easy to do using the shared-library mechanism of OC4J.

As a simple test of the JAXB 2.0 capabilities, a simple application can be used that makes use of the JAXB 2.0 features. In the example used herein, the application is a simple Web application that makes use of two POJOs that are annotated with JAXB 2.0 annotations.

Build a Test Application:
package sab.demo.jaxb.model;

import java.util.ArrayList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.*;

/**
*
@author sbutton
*
*/
@XmlType(propOrder = { "manufacturer", "model", "year",
"color"
, "registration", "owners" })
@XmlRootElement(name = "vehicle")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Vehicle {
long id;
String registration;
String manufacturer;
String model;
String year;
String color;
ArrayList<Owner> owners = new ArrayList<Owner>();

public Vehicle() {
// TODO Auto-generated constructor stub
}

...
...
}

Instances of the POJOS are then created from a JSP page, where they are marshalled into an XML document and then displayed by the JSP:
<%
try {
JAXBContext context = JAXBContext.newInstance(Vehicle.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

Vehicle xtrail = new Vehicle(1L, "Nissan", "X-Trail",
"2002"
, "Silver", "ABC-123");
xtrail.addOwner(new Owner(1L, "Fred", "Bloggs"));

Vehicle golf = new Vehicle(2L, "Volkswagen", "Golf",
"2002"
, "Silver", "XYZ-123");
golf.addOwner(new Owner(1L, "Fred", "Bloggs"));
golf.addOwner(new Owner(2L, "Freda", "Bloggs"));

StringWriter sw = new StringWriter();
marshaller.marshal(xtrail,sw);
out.println(escapeHtml(sw.toString()));

sw = new StringWriter();
marshaller.marshal(golf,sw);
out.println(escapeHtml(sw.toString()));

} catch (JAXBException e) {
e.printStackTrace(new PrintWriter(out));
}
%>
The application is then packaged up into a WAR and an EAR file ready for deployment.

Prepare the Server: Using ASC, publish a shared-library that contains the JAXB 2.0 JAR files.



Deploy the Application: When deploying the application, use the Classloading Task and import the "jaxb 2.0" shared-library so the application has access to the JAXB 2.0 implementation.



When the application is run, the Vehicle and Owner instances are marshalled to XML and displayed in the JSP page.



Voila.

8 comments:

Anonymous said...

Thanks, been looking for some information on how this can be done. Will try it out.

Daniel aka DnlCY said...

Can you do the same, but in a jdev embebbed oc4j?

ordinaryspeak said...

How can I accomplish the same with my internal OC4J server that comes bundled with JDeveloper 10.3.1.It would be really helpful if you could give me the setup steps. I had posted a query in the oracle forums
http://forums.oracle.com/forums/thread.jspa?threadID=573927&tstart=0


Thanks

Buttso said...

The embedded JDeveloper server does not have the GUI ASC to enable the shared-libraries to be so easily manipulated. Therefore, to do this, you'd need to perform a few manual steps to get the same configuration.

As a rough starter, here's what I'd start with.

1. In your JDeveloper home, do a search for the server.xml files. You'll probably see 2 of them. One of them should reside in a directory path that contains the text "embedded-oc4j".

Edit that server.xml (backup first of course) and add in a new shared-library definition that points to your JAXB 2.0 library set.

<shared-library name="jaxb" version="2.0" library-compatible="true">
<code-source path="D:\java\jaxb-ri-20070122\lib\jaxp-api.jar"/>
...
</shared-library>

What you could do to prove the existence of the shared-library is to use the admin_client.jar utility and execute the -listSharedLibraries command to list all the known shared-libraries.

To do this, start the embedded OC4J instance from within JDeveloper and take note of the RMI port value. Then use this in the connect URL.

D:\java\jdev-10131-studio\j2ee\home>java -jar admin_client.jar deployer:oc4j:loc
alhost:23891 oc4jadmin welcome -listSharedLibraries

Found 28 shared libraries:

Modifiable libraries:
jaxb version 2.0
global.libraries version 1.0
global.tag.libraries version 1.0
oracle.persistence version 1.0
oracle.expression-evaluator version 10.1.3.1
adf.oracle.domain version 10.1.3.1
adf.generic.domain version 10.1.3.1

Non-modifiable (system) libraries:
oracle.dms version 3.0
oracle.gdk version 10.1.0_2
oracle.jdbc version 10.1.0_2
oracle.xml version 10.1.0_2
oracle.cache version 10.1.3
oracle.sqlj version 10.1.3
oracle.http.client version 10.1.3
soap version 10.1.3
oracle.jwsdl version 10.1.3
apache.commons.logging version 1.0.4
util.concurrent version 1.3.2
org.jgroups version 2.3
oracle.ws.client version 10.1.3
oracle.xml.security version 10.1.3
oracle.ws.security version 10.1.3
oracle.toplink version 10.1.3
oracle.ws.reliability version 10.1.3
oracle.ws.testpage version 10.1.3
oracle.ws.core version 10.1.3
oracle.wsm version 10.1.3
xqs.d3l version 10.1.3.1.0

2. Now for your application to make use of this, you need to manually add an orion-application.xml file and specify the import-shared-library statement to pull in the JAXB 2.0. library.

<imported-shared-libraries>
<import-shared-library name="jaxb"/>
</imported-shared-libraries>

That should get you by or at least on the right path. If I get time this week, I'll it up in more detail and put it on the blog site.

Anonymous said...

HI,

I executed all the steps for embedded oc4j. However, I do not know in which directory to add the orion-application.xml file. I tried to add it in WEB-INF, then I manually created META-INF under classes in both Model AND ViewContent project but the problem persists.
Please help.

Thanks
Miklos

Buttso said...

Here's what I'd try:

From wherever you run your project -- and I get confused with the model/view content separation JDeveloper uses -- you can add the OC4J orion-application.xml deployment descriptor directly to the project -- JDeveloper should use this in conjunction with its own requirements when running the application. You add a new orion-application.xml using the File > New > General > Deployment Descriptors > OC4J Deployment Descriptor Wizard.

If that doesn't work, then you can work out where JDeveloper launches the application from by examining how it runs the application.

On the "Embedded OC4J Server Log" window, you should see a portion that looks like this:

-config D:\java\jdev-10133\jdev\system\oracle.j2ee.10.1.3.41.57\embedded-oc4j\config\server.xml

Go and look in this file and you should then see the path to the orion-application.xml that JDeveloper is using:

application name="current-workspace-app" path="D:\java\jdev-10133\jdev\mywork\war-manifest-example\war-manifest-example-oc4j-app.xml" start="true"

Looking at this file, you'll then see its actually an orion-application.xml file -- which you could edit.

But I suspect JDeveloper will overwrite this file each time you run the application so its current -- so first I'd investigage adding the orion-application.xml file directly to the project.

If all that fails, install OC4J standalone and deploy from JDeveloper to it when you need to test the application. The clean separation I find, personally speaking, to be a better option since you can more easily control the config.

Archana said...

In a oc4j, I have multiple service appliction deplyed. Only one of them needs to use jaxb2.0 Rest of them are fine with default jaxb which comes with oc4j.

How and where should I model my shared library entry.

Buttso said...

In a oc4j, I have multiple service appliction deplyed. Only one of them needs to use jaxb2.0 Rest of them are fine with default jaxb which comes with oc4j.

The level of granularity for shared-library manipulation is at the application level, accomplished via the orion-application.xml file.

Therefore I think you'd need to model your service packaging/deployment around that concept, so that for the service which required JAXB 2.0, you could perform the necessary configuration changes to import the JAXB 2.0 implementation, leaving the remainder of your services with the default implementation the container provides.