Free Software

Software Engineering with FOSS and Linux

Using JiBX with Jersey

After searching around for this for a while without much luck, I post it here hoping to save you some time. Jersey, the reference implementation of JAX-RS, typically uses JAXB to marshal and unmarshal XML. If you want to use JiBX instead, you should provide custom providers:

@Provider
public class JIBXBodyReader implements MessageBodyReader<Object> {
	public boolean isReadable(Class<?> type, Type genericType,
			Annotation[] annotations, MediaType mediaType) {		
			try {
				BindingDirectory.getFactory( type );
			} catch (JiBXException e) {
				return false;
			}
			return true;
	}

	public Object readFrom(Class<Object> type, Type genericType,
			Annotation[] annotations, MediaType mediaType,
			MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
			throws IOException, WebApplicationException {
		try {
			IBindingFactory factory = BindingDirectory.getFactory( type );
			IUnmarshallingContext context = factory.createUnmarshallingContext();
			return context.unmarshalDocument( entityStream, null );			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

@Provider
public class JIBXBodyWriter implements MessageBodyWriter<Object> {
	public long getSize(Object obj, Class<?> type, Type genericType,
			Annotation[] annotations, MediaType mediaType ) {
		return -1;
	}

	public boolean isWriteable(Class<?> type, Type genericType, 
			Annotation[] annotations, MediaType mediaType ) {		
		try {
			BindingDirectory.getFactory( type );
		} catch (JiBXException e) {
			return false;
		}
		return true;
	}

	public void writeTo(Object obj, Class<?> type, Type genericType,
			Annotation[] annotations, MediaType mediaType,
			MultivaluedMap<String, Object> headers, OutputStream outputStream)
			throws IOException, WebApplicationException {
				try {
					IBindingFactory factory = BindingDirectory.getFactory( type );
					IMarshallingContext context = factory.createMarshallingContext();
					context.marshalDocument( obj, "UTF-8", null, outputStream );
				}
				catch ( Exception e ) {
					e.printStackTrace();
				}				
	}
}

November 25, 2010 Posted by | Programming, Uncategorized, web | , , , , , , , , | 1 Comment

Building and deploying Seam/JBoss applications with Intellij IDEA 8.1

I recently got an evaluation copy of Intellij IDEA 8.1, and I have to say I love it so far. However my experience trying to build and deploy the trivial examples that ship with Seam was painful… Here are some tips, hoping it will save you a few hours of frustration… I am using JBoss 4.2.3 and Seam 2.2.0 on Ubuntu 9.04, and I am packaging the application as an EAR package.

Use a different source dir for your servlets and your EJBs. To do this, create a new directory in your project, say ejb-src, and mark it as a Source directory under the Content Root:

src-folder

then go to Project Settings -> Module -> EJB -> EJB Settings -> Source roots for EJB classes and select the ebj-src folder. This way, you will have an easier time keeping your EJB and Servlets code separate.

In your Run Configuration, you should deploy only the JavaEE Application facet. Furthermore, it must have an .ear extension, even if you are using the exploded form. You should NOT deploy the EJB and Web Facets, but they should also have .jar and .war extension, respectively, when packaged in in their container .ear package.

By all means, do NOT add jboss-seam.jar as a runtime dependency of the EJB facet! This will save you from much pain. If you do, you will see messages like this when you deploy your application:

WARN [SeamPhaseListener] There should only be one Seam phase listener per application

This eventually will lead to something like this, when you try to access a .seam page:

21:47:40,879 WARN [SeamPhaseListener] uncaught exception, passing to exception handler
java.lang.IllegalStateException: No phase id bound to current thread (make sure you do not have two SeamPhaseListener instances installed

which will eventually lead to several problems. This happens because IntelliJ will automatically generate the following manifest file in .jar/META-INF/MANIFEST.MF

Manifest-Version: 1.0
Class-Path: jboss-seam.jar
Created-By: IntelliJ IDEA

This manifest file will cause JBoss to load jboss-seam.jar once when the ebj jar is deployed, and again when the ear is deployed, leading to a mixup later on. What you should do is add a library containing jboss-seam.jar to your JavaEE Application deployment settings directly. When you do this, IntelliJ will automatically place it in the lib/ directory of the ear package. Use Edit… to place it at the root. You package settings should look like this:

deploy

Hope this helps :)

August 6, 2009 Posted by | Programming | , , , , , , , | 4 Comments