Hello together,
i use jackson-module-hibernate to solve the issue that jackson cannot serialize lazy loaded objects:
Code:
31.03.2011 01:12:14 org.apache.catalina.core.StandardWrapperValve invoke
SCHWERWIEGEND: Servlet.service() for servlet *** Web Service threw exception
org.codehaus.jackson.map.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: de.***ReturnSearch["rideSearch"]->de***RideSearch["user"]->de***model.User_$$_javassist_1["handler"])
With the jackson-module-hibernate (
https://github.com/FasterXML/jackson-module-hibernate) this is solved. However the issue then is that each object, which is serialized contains "handler":{} and "hibernateLazyInitializer":{} in the json file, which I try to get rid of, but haven’t found a solution yet. Anybody has a hint?
thanks to the great work and support you have all done the following combination nearly works:
• Jersey
• Jackson-module-hibernate
• Jaxb annotations
• Hibernate
• Tomcat
I would like to share that with the community. There is nothing really new.
It is just a combination of different tutorials but it could help new people. At the end of the mail I will post all necessary source. Where would be the correct place to post the source? Any idea?
Key features of this source:
• Hibernate sessions stay open until the entire jersey work is done
http://www.martin-probst.com/blog/2008/ ... hibernate/ • Lazy initialization is done by Jackson-module-hibernate
o Registration of object mapper:
http://wiki.fasterxml.com/JacksonFAQJaxRs (thanks to Tatu)
• Using Jaxb annotations
wiki.fasterxml.com/JacksonJAXBAnnotations
---------------------
==== not sure if this class is actually necessary - any feedback? Thank ===
Code:
import com.sun.jersey.api.json.JSONConfiguration;
import com.sun.jersey.api.json.JSONJAXBContext;
import com.sun.jersey.core.spi.scanning.PackageNamesScanner;
import com.sun.jersey.spi.scanning.AnnotationScannerListener;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@Provider
public final class JAXBContextResolver implements ContextResolver<JAXBContext> {
private JAXBContext context;
private Class[] types;
public JAXBContextResolver() throws Exception {
PackageNamesScanner pns = new PackageNamesScanner(new String[] {"de.***.backend"});
AnnotationScannerListener asl = new AnnotationScannerListener(XmlRootElement.class, XmlType.class);
pns.scan(asl);
Set<Class<?>> jaxbClasses = asl.getAnnotatedClasses();
this.context = new
JSONJAXBContext(JSONConfiguration.natural().build(),
types = jaxbClasses.toArray(new Class[jaxbClasses.size()]));
}
public JAXBContext getContext(Class<?> objectType) {
return context;
}
}
--------------------------------------
Code:
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.*;
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.xc.JaxbAnnotationIntrospector;
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonContextResolver implements ContextResolver<ObjectMapper> {
private ObjectMapper objectMapper;
public JacksonContextResolver() throws Exception {
this.objectMapper = new HibernateAwareObjectMapper(); //TODO for production this.objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PR
OPERTIES, false);
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
// make deserializer use JAXB annotations (only)
this.objectMapper.getDeserializationConfig().setAnnotationIntrospector(intro
spector);
// make serializer use JAXB annotations (only)
this.objectMapper.getSerializationConfig().setAnnotationIntrospector(introsp
ector);
}
public ObjectMapper getContext(Class<?> objectType) {
return objectMapper;
}
}
-------------------------------------
Code:
package de.***.backend.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.Application;
import org.hibernate.HibernateException;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import de.***.backend.hibernate.HibernateUtil;
import de.***.backend.util.BodyErrorException;
import de.***.backend.util.ExecFailureException;
import de.***.backend.util.ParamErrorException;
import de.***.backend.web.enums.Statuscode;
public class PtxServletContainer extends ServletContainer {
private static final long serialVersionUID = -1918393089058874244L;
public PtxServletContainer() {
super();
}
public PtxServletContainer(Class<? extends Application> appClass) {
super(appClass);
}
public PtxServletContainer(Application app) {
super(app);
}
@Override
public void service(HttpServletRequest req, HttpServletResponse
resp) throws ServletException, IOException {
String method = req.getMethod();
boolean readonly = "GET".equals(method) || "HEAD".equals(method);
try {
// open session and transaction
HibernateUtil.beginTransaction();
// call wrapped jersey servletContainer
super.service(req, resp);
// FIXME LUKAS HELP wird eine runtime exception geworfen weil zb der Algo nicht erreichbar ist, so wird dann eine jersey exception geworfen die nicht gefangen wird (warum auch immer) und eine html datei wird zurückgegeben
// commit | rollback transaction
if (readonly) {
HibernateUtil.rollbackTransaction();
} else {
HibernateUtil.commitTransaction();
}
// TODO statt throw e ändere den rückgabewert, statuscode und so weiter
} catch (HibernateException e) {
e.printStackTrace();
HibernateUtil.rollbackTransaction();
resp.setStatus(500);
//
status.setValues(Statuscode.EXEC_FAILURE,e.getMessage());
} catch (BodyErrorException e) {
e.printStackTrace();
HibernateUtil.rollbackTransaction();
resp.setStatus(400);
//
status.setValues(Statuscode.BODY_ERROR,e.getMessage());
} catch (ParamErrorException e) {
e.printStackTrace();
HibernateUtil.rollbackTransaction();
resp.setStatus(400);
//
status.setValues(Statuscode.PARAM_ERROR,e.getMessage());
} catch (ExecFailureException e) {
e.printStackTrace();
HibernateUtil.rollbackTransaction();
resp.setStatus(500);
//
status.setValues(Statuscode.EXEC_FAILURE,e.getMessage());
} catch (Exception e) {
e.printStackTrace();
HibernateUtil.rollbackTransaction();
resp.setStatus(500);
//
status.setValues(Statuscode.EXEC_FAILURE,e.getMessage());
} finally {
try {
HibernateUtil.closeSession();
} catch (Exception e) {
e.printStackTrace();
resp.setStatus(500);
// throw e;
//
status.setValues(Statuscode.EXEC_FAILURE,e.getMessage());
}
}
}
}
----------------------
Web.xml extract
Code:
<servlet>
<servlet-name>*** Web Service</servlet-name>
<servlet-class>de.***.backend.web.PtxServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>de.***.backend.web;org.codehaus.jackson.jaxrs</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>com.sun.jersey.api.container.filter.RolesAllowedResourceFilterF
actory</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>