1

I have a value object that I want to expose via a json rest call. I have numerous other rest calls in my project that work just fine but this 1 doesnt for some reason. When I try and return this object back - I get an exception that I dont know how to resolve

The value object code is as follows (minus accessor methods)

package com.test.domain.dao;

    import java.io.Serializable;
    import java.util.HashSet;
    import java.util.Set;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;

    import org.hibernate.annotations.Cascade;
    import org.hibernate.annotations.CascadeType;

    import com.fasterxml.jackson.annotation.JsonIgnore;

    @Entity
    @Table(name = "company")
    public class CompanyVO extends BaseDAOVO implements Serializable{


        /**
         * 
         */
        private static final long serialVersionUID = 4278014816235716721L;

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id", unique = true, nullable = false)
        private Integer id;

        @Column(name = "companyName", unique = true, nullable = false, length = 200)
        private String companyName;

        @Column(name = "companyLogo", unique = true, nullable = false, length = 10000)
        private String companyLogo;

        @Column(name = "isDefaultCompany",nullable = false)
        private boolean isDefaultCompany;

        @OneToMany(fetch = FetchType.LAZY, mappedBy = "company")
        @Cascade({ CascadeType.DELETE, CascadeType.SAVE_UPDATE })
        @JsonIgnore
        private Set<UserVO> users = new HashSet<UserVO>(0);

    }

My rest method for returning the company object via json is as follows

/**
     * Method to get the company for a particular userId 
     * @param userId
     * @return
     */
    @RequestMapping(value = { GET_COMPANY_FOR_USER }, method = RequestMethod.GET)
    public CompanyVO getCompanyForUser(
            @PathVariable(value = RestConstants.USER_ID_PLACEHOLDER) Integer userId) {

        LOG.info("Entered getCompanyForUser method - userId:{}", userId);


        CompanyVO companyVO = companyServices.getCompanyForUser(userId);

        LOG.info("Exiting getCompanyForUser method");
        return companyVO;
    }

When I call this particular rest method i get the following errors in the stacktrace

[2015-03-02 11:12:30,229] [http-bio-8080-exec-8] [INFO] com.test.webapp.controllers.rest.CompanyRestController - Entered getCompanyForUser method - userId:1
[2015-03-02 11:12:30,248] [http-bio-8080-exec-8] [INFO] com.test.webapp.controllers.rest.CompanyRestController - Exiting getCompanyForUser method
[2015-03-02 11:12:30,267] [http-bio-8080-exec-8] [INFO] c.t.webapp.controllers.exceptions.GlobalExceptionHandlerController - Entered exception method: e:{}
org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.test.domain.dao.CompanyVO_$$_jvstb99_6["handler"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.test.domain.dao.CompanyVO_$$_jvstb99_6["handler"])
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:238) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161) ~[spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101) ~[spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:202) ~[spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126) ~[spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777) ~[spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:706) ~[spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943) ~[spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) ~[spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) [spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:620) [servlet-api.jar:na]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) [spring-webmvc-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [servlet-api.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) [catalina.jar:7.0.54]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.54]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat7-websocket.jar:7.0.54]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.54]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.54]
    at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:150) [spring-orm-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.54]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.54]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:186) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) [spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) [spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.54]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.54]
    at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:118) [spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.54]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.54]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [catalina.jar:7.0.54]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.54]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [catalina.jar:7.0.54]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) [catalina.jar:7.0.54]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [catalina.jar:7.0.54]
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [catalina.jar:7.0.54]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.54]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [catalina.jar:7.0.54]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) [tomcat-coyote.jar:7.0.54]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) [tomcat-coyote.jar:7.0.54]
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316) [tomcat-coyote.jar:7.0.54]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_40]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_40]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-coyote.jar:7.0.54]
    at java.lang.Thread.run(Thread.java:724) [na:1.7.0_40]
Caused by: com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.test.domain.dao.CompanyVO_$$_jvstb99_6["handler"])
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59) ~[jackson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:26) ~[jackson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:505) ~[jackson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639) ~[jackson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152) ~[jackson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:114) ~[jackson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1887) ~[jackson-databind-2.4.3.jar:2.4.3]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    ... 50 common frames omitted

Any assistance in sorting this would be much appreciated

Damien Gallagher
  • 981
  • 4
  • 13
  • 25

3 Answers3

2

In addition to the solution you've already found, you can consider two more solutions. One registering the Hibernate4Module with the ObjectMapper, which will register HibernateProxySerializer, already equipped with the intelligence to deal with proxies, you can check the code not difficult to understand. Registering is also quite straight forward, form their docs:

public class HibernateAwareObjectMapper extends ObjectMapper {

    public HibernateAwareObjectMapper() {
        registerModule(new Hibernate4Module());
    }
}

than register

 <mvc:annotation-driven>
        <mvc:message-converters>
            <!-- Use the HibernateAware mapper instead of the default -->
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="path.to.your.HibernateAwareObjectMapper" />
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

Another solution is to use a DTO object, adds some boiler plate code when copying values from an entity, but gives you more control and decouples the representation from the an actual entity

Master Slave
  • 27,771
  • 4
  • 57
  • 55
2

According to masterSlave provided link and solution, i adopt it to Spring Boot. i face the problem at my Spring Boot project and solve it to create HibernateAwareObjectMapper and define a custom new MappingJackson2HttpMessageConverter like below.

First add dependecy for hibernate4 to pom.xml

<dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-hibernate4</artifactId>
            <version>2.5.3</version>
        </dependency>

Create HibernateAwareObjectMapper class

/**
 * https://github.com/FasterXML/jackson-datatype-hibernate
 *
 */
public class HibernateAwareObjectMapper extends ObjectMapper {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public HibernateAwareObjectMapper() {
        registerModule(new Hibernate4Module());
    }
}

Add custom MappingJackson2HttpMessageConverter class to Application.java

@Bean
    public MappingJackson2HttpMessageConverter customJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        HibernateAwareObjectMapper hibernateAwareObjectMapper = new HibernateAwareObjectMapper();
        jsonConverter.setObjectMapper(hibernateAwareObjectMapper);
        return jsonConverter;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(customJackson2HttpMessageConverter());
        super.addDefaultHttpMessageConverters(converters);
    }
erhun
  • 3,549
  • 2
  • 35
  • 44
  • This does not provide an answer to the posted question; it's a "thank you" directed at [a previous answer](http://stackoverflow.com/a/28808817/1677912). [Please use Answers exclusively to answer the question](//meta.stackoverflow.com/q/92107). You have gained sufficient [privileges](//stackoverflow.com/privileges) to upvote answers you like, which is the Stack Overflow way of saying thank you. – Mogsdad Apr 19 '16 at 01:28
  • @MogsdadAccording to problem Hibernate,Spring and Jackson usage cause a problem in lazy initilization properties to convert as json which is provided by jackson. MasterSlave give the answer as Spring MVC perspective so i want to contribute as a solution with Spring Boot. Because i add a custom MappingJackson2HttpMessageConverter implementation usage on Spring Boot which is worth to contribute. I didn't find any other answers on SO like this. If it isn't get any upvote(which means useful for someone), i will be delete with pleasure :) thanks for your comment. – erhun Apr 19 '16 at 06:25
  • @RafaelOsipov I edit the answer as you mentioned. – erhun Apr 19 '16 at 08:40
-3

Thanks to Evgeni for providing a link which contained the answer Annotating my CompanyVO bean with the following annotation removed the error @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

Damien Gallagher
  • 981
  • 4
  • 13
  • 25