java Spring Rest - 异常生成 Json 数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28808412/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 14:12:51  来源:igfitidea点击:

Spring Rest - Exception Producing Json Data

javajsonspringhibernaterest

提问by Damien Gallagher

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

我有一个值对象,我想通过 json rest 调用公开它。我的项目中有许多其他的休息电话,它们工作得很好,但由于某种原因,这 1 个电话没有。当我尝试返回这个对象时 - 我得到一个我不知道如何解决的异常

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.Hymanson.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

我的通过json返回公司对象的rest方法如下

/**
     * 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

当我调用这个特定的 rest 方法时,我在堆栈跟踪中收到以下错误

[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.Hymanson.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.AbstractHymanson2HttpMessageConverter.writeInternal(AbstractHymanson2HttpMessageConverter.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.Hymanson.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.Hymanson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59) ~[Hymanson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.Hymanson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:26) ~[Hymanson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.Hymanson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:505) ~[Hymanson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.Hymanson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639) ~[Hymanson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.Hymanson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152) ~[Hymanson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.Hymanson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:114) ~[Hymanson-databind-2.4.3.jar:2.4.3]
    at com.fasterxml.Hymanson.databind.ObjectMapper.writeValue(ObjectMapper.java:1887) ~[Hymanson-databind-2.4.3.jar:2.4.3]
    at org.springframework.http.converter.json.AbstractHymanson2HttpMessageConverter.writeInternal(AbstractHymanson2HttpMessageConverter.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

对此进行排序的任何帮助将不胜感激

回答by Master Slave

In addition to the solution you've already found, you can consider two more solutions. One registering the Hibernate4Modulewith 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:

除了您已经找到的解决方案之外,您还可以考虑另外两个解决方案。一个注册Hibernate4ModuleObjectMapper,这将注册HibernateProxySerializer,已经配备了智能处理代理,你可以检查代码就不难理解了。注册也很简单,形成他们的文档:

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.MappingHymanson2HttpMessageConverter">
                <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

另一种解决方案是使用 DTO 对象,在从实体复制值时添加一些样板代码,但为您提供更多控制并将表示与实际实体分离

回答by erhun

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 HibernateAwareObjectMapperand define a custom new MappingHymanson2HttpMessageConverterlike below.

根据 masterSlave 提供的链接和解决方案,我将其用于 Spring Boot。我在我的 Spring Boot 项目中遇到了这个问题,并解决了它来创建HibernateAwareObjectMapper和定义一个自定义的 new,MappingHymanson2HttpMessageConverter如下所示。

First add dependecy for hibernate4 to pom.xml

首先将 hibernate4 的依赖添加到 pom.xml

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

Create HibernateAwareObjectMapperclass

创建HibernateAwareObjectMapper

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

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

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

Add custom MappingHymanson2HttpMessageConverterclass to Application.java

将自定义MappingHymanson2HttpMessageConverter类添加到 Application.java

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

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(customHymanson2HttpMessageConverter());
        super.addDefaultHttpMessageConverters(converters);
    }

回答by Damien Gallagher

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"})

感谢 Evgeni 提供包含答案的链接 使用以下注释注释我的 CompanyVO bean 删除了错误 @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})