Coder Social home page Coder Social logo

fasterxml / jackson-datatype-hibernate Goto Github PK

View Code? Open in Web Editor NEW
313.0 30.0 107.0 1.65 MB

Add-on module for Jackson JSON processor which handles Hibernate (https://www.hibernate.org/) datatypes; and specifically aspects of lazy-loading

Java 100.00%

jackson-datatype-hibernate's Introduction

Project to build Jackson module (jar) to support JSON serialization and deserialization of Hibernate (https://hibernate.org) specific datatypes and properties; especially lazy-loading aspects.

Maven Central Javadoc

Status

As of version 2.0 module is usable and used by non-trivial number of developers and projects.

Note: Hibernate 4.x and 5.x are supported (5.x starting with Jackson 2.6), but they require different jar, and Maven artifact names (and jar names differ). This document refers to "Hibernate 5" version, but changes with 4.x should require little more than replacing "5" in names with "4".

Hibernate 3.x was supported up to Jackson 2.12 but is no longer supported at and after 2.13

Jackson 2.13 adds Support for "Hibernate 5 Jakarta" variant (for Hibernate 5.5 and beyond); see below for more information.

Jackson 2.15 adds Support for Hibernate 6.x; see below for more information.

JDK requirements

Before Jackson 2.15, baseline JDK needed for building for JDK 8 and all module variants worked on Java 8.

With Jackson 2.15, JDK 11 will be required to build: all modules run on Java 8 except for Hibernate 6.x module which requires Java 11 like Hibernate 6.x itself.

Javax vs Jakarta

Due to changes related to Java EE to Jakarta EE transition (also known as "JAXB to Jakarta" etc etc), there are 2 variants of Hibernate 5 module:

  • One that works with "old" JAXB/JavaEE APIs: jackson-datatype-hibernate5
  • One that works with "new" Jakarta APIs: jackson-datatype-hibernate5-jakarta

Note that for Hibernate 4.x only old APIs matter; and for 6.x and later only new (Jakarta) APIs are used -- so there are no separate modules.

Usage

Maven dependency

To use module on Maven-based projects, use following dependency (with whatever is the latest version available):

<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-hibernate5</artifactId>
  <version>2.14.2</version>
</dependency>    

or whatever version is most up-to-date at the moment;

Note that you need to use "jackson-datatype-hibernate4" for Hibernate 4.x.

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

if you plan to use Hibernate 5.5 with the Jakarta Persistence API 3.0; you will need the jakarta suffixed dependency for Hibernate 5.5:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-hibernate5-jakarta</artifactId>
    <version>2.14.2</version>
</dependency>

you will need to use "jackson-datatype-hibernate6" for Hibernate 6.x (when v2.15.0 is released):

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-hibernate6</artifactId>
    <version>2.15.0</version>
</dependency>

Registering module

Like all standard Jackson modules (libraries that implement Module interface), registration is done as follows:

ObjectMapper mapper = new ObjectMapper();
// for Hibernate 4.x:
mapper.registerModule(new Hibernate4Module());
// or, for Hibernate 5.x
mapper.registerModule(new Hibernate5Module());
// or, for Hibernate 5.5+ with Jakarta
mapper.registerModule(new Hibernate5JakartaModule());
// or, for Hibernate 6.x
mapper.registerModule(new Hibernate6Module());

after which functionality is available for all normal Jackson operations.

Avoiding infinite loops

Using with Spring MVC

Although more common way would be to register the module explicitly, it is alternatively possible to just sub-class ObjectMapper and register the module in constructor.

public class HibernateAwareObjectMapper extends ObjectMapper {
    public HibernateAwareObjectMapper() {
        // This for Hibernate 5; change 5 to 4 if you need to support
        // Hibernate 4 instead
        registerModule(new Hibernate5Module());
    }
}

Then add it as the objectmapper to be used

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

If mvc:annotation-driven is not being used, it can be added as a jsonconverter to the messageconverters of RequestMappingHandlerAdapter.

Other

Project Wiki contains links to Javadocs and downloadable jars (from Central Maven repository).

jackson-datatype-hibernate's People

Contributors

abryzak avatar arturdryomov avatar bedag-moo avatar christophercurrie avatar cowtowncoder avatar cwinters avatar dependabot[bot] avatar donhuvy avatar drvdijk avatar eoger avatar jobosk avatar jon5477 avatar matsemann avatar mshima avatar mtyurt avatar peruzzo avatar pjfanning avatar prb avatar ralscha avatar reda-alaoui avatar shushkovroman avatar splatch avatar taha-di-nero avatar tatu-at-salesforce avatar tsachev avatar valery1707 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jackson-datatype-hibernate's Issues

When JPA annotations are not used, collections are always loaded.

When JPA annotations are not used (i.e. in Grails), PersistentCollectionSerializer.usesLazyLoading() erroneously assumes that lazy loading is not used. Lazy loading is default for hibernate and for gorm in grails. Consequently it should be default in Jackson too.

With all this in mind, usesLazyLoading implementation should be changed in following way:

    protected boolean usesLazyLoading(BeanProperty property)
    {
        if (property != null) {
            // As per [Issue#36]
            ElementCollection ec = property.getAnnotation(ElementCollection.class);
            if (ec != null) {
                return (ec.fetch() == FetchType.LAZY);
            }
            OneToMany ann1 = property.getAnnotation(OneToMany.class);
            if (ann1 != null) {
                return (ann1.fetch() == FetchType.LAZY);
            }
            OneToOne ann2 = property.getAnnotation(OneToOne.class);
            if (ann2 != null) {
                return (ann2.fetch() == FetchType.LAZY);
            }
            ManyToOne ann3 = property.getAnnotation(ManyToOne.class);
            if (ann3 != null) {
                return (ann3.fetch() == FetchType.LAZY);
            }
            ManyToMany ann4 = property.getAnnotation(ManyToMany.class);
            if (ann4 != null) {
                return (ann4.fetch() == FetchType.LAZY);
            }
            // bug fix bellow:
            // If no annotations are found, assume lazy loading.
            return true
        }
        return false;
    }

Spring Controller annotated with @JsonView and hibernate4

Hello,
It isn't a bug, bug nasty behavior.
I configure my MappingJackson2HttpMessageConverter for using ObjectMapper and Hibernate4Module with SessionFactory

Spring along @JsonView-aware Controller has been used
see for more info: "Jacksonโ€™s @JsonView is supported directly on @ResponseBody"

I supposed that all Lazy fields will be initiated and serialized, but got "could not initialize proxy - no Session" on

@ManyToOne(fetch = FetchType.LAZY, optional = false) 
private Test test;

exception goes from
com.fasterxml.jackson.datatype.hibernate4.HibernateProxySerializer#findProxied

return init.getImplementation(); 

Is it expected?

Type information not output to json

I have a hibernate entity with a polymorphic collection annotated with both Jaxb and JPA annotations like so:

    @XmlElementRefs({
            @XmlElementRef(type = Question.class),
            @XmlElementRef(type = ChoiceQuestion.class),
            @XmlElementRef(type = AgeRangeQuestion.class),
            @XmlElementRef(type = TextQuestion.class),
            @XmlElementRef(type = NumericQuestion.class),
            @XmlElementRef(type = BrandTrackingQuestion.class),
            @XmlElementRef(type = RdTextQuestion.class),
            @XmlElementRef(type = AceDiagnosticQuestion.class)
    })
    @ManyToMany(fetch = FetchType.LAZY)
    @Fetch(value = FetchMode.SUBSELECT)
    @OrderColumn(name = "question_index")
    public List<Question> getQuestions() {
        return questions;
    }

With my objectmapper configured as below, I get type information in the output:

        ObjectMapper mapper = new ObjectMapper();
        JaxbAnnotationModule jaxbAnnotationModule = new JaxbAnnotationModule();
        jaxbAnnotationModule.setPriority(JaxbAnnotationModule.Priority.PRIMARY);
        mapper.registerModule(jaxbAnnotationModule);

Json looks like so:

{
...
  "questions": [
    {
      "textQuestion": {
        "questionUuid": "601dae29-e6d8-4479-93e2-ad22b97dcae0",
        ...
      }
    },
    {
      "choiceQuestion": {
        "questionUuid": "601dae29-e6d8-4479-93e2-ad22b97dcae0",
        ...
    }
  ]
}

I then retry with the hibernate4module registered like so:

        ObjectMapper mapper = new ObjectMapper();
        JaxbAnnotationModule jaxbAnnotationModule = new JaxbAnnotationModule();
        jaxbAnnotationModule.setPriority(JaxbAnnotationModule.Priority.PRIMARY);
        mapper.registerModule(jaxbAnnotationModule);

        Hibernate4Module hibernate4Module = new Hibernate4Module();
hibernate4Module.disable(Hibernate4Module.Feature.USE_TRANSIENT_ANNOTATION);
        mapper.registerModule(hibernate4Module);

Which gives me output that is missing the type info no matter how I configure the modules or set their priorities:

{
  "questions": [
    {
      "questionUuid": "e12f3ab7-b61e-4d63-8a2f-4475c9ce92db",
        ...
    },
    {
      "questionUuid": "601dae29-e6d8-4479-93e2-ad22b97dcae0",
      ...
    }
  ]
}

I tried using jackson annotations and introspector in place of jaxb and got the exact same behavior, type info output properly when Hibernate4Module is not registered, no type info with it registered.

Anyone know how I might get this working?

The hibernate4module is working perfectly in terms of preventing lazy init exceptions, btw.

Make skipping of @Transient fields optional

In our application we use some Transient fields to pass information in the JSON that did not necessarily come from the database. When adding jackson-module-hibernate, these fields are now ignored. It would be nice if the processing of @transient annotations was an optional feature.

Currently we modify HibernateModule.java and comment out the following line in setupModule(...):

//context.appendAnnotationIntrospector(new HibernateAnnotationIntrospector());

@JsonView in conflict with @Transient

I was redirectd from: FasterXML/jackson-annotations#70

If there is a field annotated with @Transient (javax.persistence.Transient) it's ignored, but if I force to show it for instance with @JsonView(Foo.class) it is always serialized, doesn't matter if I use the Boo.class or Other.class view. always show it.

A scenario:

class Views {
    public static interface PublicView {}
    public static interface PrivateView {}
}
class Foo {
    private String aaa;
    @Transient
    private String bbb;
    @Transient
    @JsonView(PublicView.class)
    private String ccc;
    @JsonView(PrivateView.class)
    private String ddd;
}

What I get:
writer without specify view: {aaa:"xxx", ccc:"xxx", ddd:"xxx"}
writer with PublicView: {aaa:"xxx", ccc:"xxx"}
writer with PrivateView: {aaa:"xxx", ccc:"xxx", ddd:"xxx"}

What I spected:
writer without specify view: {aaa:"xxx", ccc:"xxx", ddd:"xxx"}
writer with PublicView: {aaa:"xxx", ccc:"xxx"}
writer with PrivateView: {aaa:"xxx", ddd:"xxx"}

Infinite recursion due to `@JsonIgnoreProperties` not applicable to `List` valued property

I have a stackoverflow problem, but it occurs only depending on the entity that initialize first.

@Entity @Table(name="contrato")
public class Contrato {

    @Id
    private Long id;

    private String numeroContrato;

    @OneToMany(mappedBy="contrato") @JsonIgnoreProperties("contrato")
    private List<Parcela> parcelas;

    @OneToMany(mappedBy="contrato") @JsonIgnoreProperties("contrato")
    private List<Liquidacao> liquidacoes;
}

@Entity @Table(name="contrato_parcela")
public class Parcela {

    @Id
    private Long id;

    private Integer numeroParcela;  

    @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="contrato_id")
    private Contrato contrato;
}

@Entity @Table(name="contrato_liquidacao")
public class Liquidacao {

    @Id
    private Long id;

    private BigDecimal valorTotal;

    @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="contrato_id")
    private Contrato contrato;

    @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="contrato_parcela_id") @JsonIgnoreProperties("contrato")
    private Parcela parcela;
}

This block below works perfectly with the expected return: {"numeroContrato":"101-6861944","parcelas":[{"numeroParcela":3}],"liquidacoes":[{"valorTotal":91548.00,"parcela":{"numeroParcela":3}}]}

final Contrato contrato = em.find(Contrato.class, 1L);
Hibernate.initialize(contrato.getParcelas());
Hibernate.initialize(contrato.getLiquidacoes());
mapper.writer().writeValueAsString(contrato);

But that other code block, where I changed the boot order of the relationship I have a stackoverflow.

Contrato contrato = em.find(Contrato.class, 1L);
Hibernate.initialize(contrato.getLiquidacoes());
Hibernate.initialize(contrato.getParcelas());
mapper.writer().writeValueAsString(contrato); 

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: teste.jackson.Contrato["parcelas"]->org.hibernate.collection.internal.PersistentBag[0]->teste.jackson.Parcela["contrato"]->teste.jackson.Contrato["parcelas"]->org.hibernate.collection.internal.PersistentBag[0]->teste.jackson.Parcela["contrato"]->teste.jackson.Contrato["parcelas"]->org.hibernate.collection.internal.PersistentBag[0]->teste.jackson.Parcela["contrato"]->teste.jackson.Contrato["parcelas"]->org.hibernate.collection.internal.PersistentBag[0] ...

could not initialize proxy - no Session

root cause org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
    org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
    com.fasterxml.jackson.datatype.hibernate4.HibernateProxySerializer.findProxied(HibernateProxySerializer.java:124)
    com.fasterxml.jackson.datatype.hibernate4.HibernateProxySerializer.serialize(HibernateProxySerializer.java:62)
    com.fasterxml.jackson.datatype.hibernate4.HibernateProxySerializer.serialize(HibernateProxySerializer.java:23)
    com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:544)
    com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:551)
    com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:143)
    com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:120)
    com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1728)
    org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.writeInternal(MappingJackson2HttpMessageConverter.java:193)
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:179)
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:148)
    org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:124)
    org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:69)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:746)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:687)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:811)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

I use hibernate 4 and spring data for persistence. I have no idea how to fix this issue.

LazyLoadingException when using @ElementCollection

When using javax.persistence.ElementCollection and hibernate 4.2.1.Final I get the undesirable LazyLoadingException.

Anyway, Is ElementCollection supported by jackson-module-hibernate? Is it a known bug? Or something is wrong with my project?

NOTE: As far as i could guess proxys are quite similar in both ordinary @OneToMany collection and @ElementCollection. Anyway, using value types is quite a good practice in order to achieve data integrity and adjust life cycle of child attributes.

serialization of a getter

Hey there, in version 2.2.3 I get all my getters that not mark with JSON ignore to be serialized. But, when the lastest version 2.4.2. the getters that do not have any property related to them don't get serialized.

Code example:

@LastModifiedBy
    @ManyToOne(optional = true)
    @JoinColumn(name="MODIFIER_ID", referencedColumnName = "ID")
     private User modifiedBy;

public String getModifierName() {
    if (modifiedBy == null) {
        return "";
    }
    return modifiedBy.getFirstName() + " " + modifiedBy.getLastName();
}

To sum up:

In 2.2.3 I will have modifierName field in the json out. But, in 2.4.2 I wont get this kind of field

an exception

hi guys

When use module-hibernate3 then throw an exception,Can someone help me

com.fasterxml.jackson.databind.JsonMappingException: Failed to instantiate standard serializer (of type com.fasterxml.jackson.databind.ser.std.NullSerializer): Class com.fasterxml.jackson.databind.ser.BasicSerializerFactory can not access a member of class com.fasterxml.jackson.databind.ser.std.NullSerializer with modifiers "private";the exceprion was at items serializationใ€‚

jackson-databind 2.2

My domain code:

public class Order{
private String id;
private String name;
private Set items;
//gettter... setter
}

public class Item{
private String id;
private String name;
private String remark;
//gettter... setter
}

PersistentCollectionSerializer - Serializing a HashMap throws a NullPointerException

com.fasterxml.jackson.databind.JsonMappingException: [no message for java.lang.NullPointerException]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:129)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:2718)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2193)

If I change the following code in createContextual:
if (_forceLazyLoading || !usesLazyLoading(property)) {
return _serializer;
}

to this:
if (_forceLazyLoading || !usesLazyLoading(property)) {
return (JsonSerializer) ((ContextualSerializer) _serializer).createContextual(provider, property);
}

it appears to fix the problem.

Here is a TestNG test that exhibits this behavior:

package com.healthwyse.util;

import static org.testng.Assert.*;

import java.io.StringWriter;
import java.util.*;

import org.testng.annotations.Test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;

public class SerializeTest {
@test
public void testSerialization() {
ObjectMapper mapper = new HibernateAwareObjectMapper();

    Map<String, String> map = new HashMap<>();
    map.put("a","b");

    StringWriter sw = new StringWriter();
    try {
        mapper.writeValue(sw, map);
    }
    catch (Exception e) {
        e.printStackTrace();
        fail();
    }

    assertEquals(sw.toString(), "{\"a\":\"b\"}");
}


@SuppressWarnings("serial")
private class HibernateAwareObjectMapper extends ObjectMapper {
    {
        registerModule(new Hibernate4Module());

    }
}

}

NPE when serializing PersistentCollection as root object

When using Hibernate4 module and trying to serialize a PersistentCollection subclass as a root object, PersistentCollectionSerializer throws a NullPointerException (line 70 of PersistentCollectionSerializer.java). This seems to be caused by DefaultSerializerProvider calling findTypedValueSerializer with null third parameter on line 87 of DefaultSerializerProvider.java.

Using Hibernate Module for lazy loading does not work with @JsonIdentityInfo

I'm not sure if this is because the proxy does not have the annotation on it or if it is something else.

We have several entities with cyclic dependencies and were originally defined as EAGER loading. We added the @JsonIdentityInfo on those classes and they were serializing fine.

I changed several of them to LAZY loading for performance reasons, and now it seems that when the classes that are proxied are serialized, the @JsonIdentityInfo is not being honored by the Hibernate 4 Module.

We are using JBoss 7.2.0 with RestEasy. I added the appropriate dependencies to my Maven pom, wrote a custom provider and simply instantiated an ObjectMapper and registered the Hibernate4Module.

When I retrieve the object via a call to RestEasy, it attempt to serialize it using the ObjectMapper I created, but it ends with an infinite loop and eventually throws an exception. Similar to the way Jackson 1 used to react with cyclic dependencies. It prints the same two error lines multiple times in the stack trace (I am cutting it off after a few....it's probably several hundred times repeated:

23:46:41,588 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/mission_planning_war].[Resteasy]] (http-/127.0.0.1:8080-1) JBWEB000236: Servlet.service() for servlet Resteasy threw exception: java.lang.ClassNotFoundException: com.fasterxml.jackson.databind.JsonMappingException$Reference from [Module "deployment.elint_ear-0.0.1-SNAPSHOT.ear.mission_planning_war-0.0.1-SNAPSHOT.war:main" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190) [jboss-modules.jar:1.2.0.CR1]
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468) [jboss-modules.jar:1.2.0.CR1]
at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456) [jboss-modules.jar:1.2.0.CR1]
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398) [jboss-modules.jar:1.2.0.CR1]
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120) [jboss-modules.jar:1.2.0.CR1]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:613) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:142) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.datatype.hibernate4.HibernateProxySerializer.serialize(HibernateProxySerializer.java:75) [jackson-datatype-hibernate4-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.datatype.hibernate4.HibernateProxySerializer.serialize(HibernateProxySerializer.java:24) [jackson-datatype-hibernate4-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:569) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:597) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:142) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:117) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:23) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:186) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:569) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:597) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:142) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.datatype.hibernate4.HibernateProxySerializer.serialize(HibernateProxySerializer.java:75) [jackson-datatype-hibernate4-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.datatype.hibernate4.HibernateProxySerializer.serialize(HibernateProxySerializer.java:24) [jackson-datatype-hibernate4-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:569) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:597) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:142) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:117) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:23) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:186) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:569) [jackson-databind-2.2.1.jar:2.2.1]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:597) [jackson-databind-2.2.1.jar:2.2.1]

Can't set ObjectMapper with Jackson 2

My project uses Hibernate 4.1, Jackson 2, and Spring 3.1 using Java configuration instead of xml configuration.

I probably wouldn't have even noticed this issue if I were using xml configuration, but when using java configuration and trying to set the objectMapper in the MappingJacksonHttpMessageConverter bean, your setObjectMapper method asks for an object which is: org.codehaus.jackson.map.ObjectMapper, however in Jackson 2 they changed their groupId to be com.fasterxml.jackson, so java shows a compiler error.

I wanted to use your project, but it looks like it is incompatible with my project's configuration, and extending and modifying your class isn't an option for this project.

Spring Config How to

EDIT: Added properety tag to injct HibernateAwareObjectMapper to MappingJacksonJsonView which I think is the correct way of doing it, but it still doesn't work with v1.8.

Would you mind sharing the appropriate (complete) Spring Configuration to make this work?
I'm currently using

<mvc:annotation-driven /> 

and something like:

<bean
    class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json" />
        </map>
    </property>
    <property name="defaultViews">
        <list>


ย ย ย ย ย ย ย ย ย ย ย ย 
ย ย ย ย ย ย ย ย ย ย ย ย 
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย 
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย 
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย 
ย ย ย ย ย ย ย ย ย ย ย ย 

    </list>
    </property>
</bean>

I added the config in the Readme, but it doesn't seem to working with my setup.
Maybe I have to unroll the <mvc:annotation-driven /> ?

Is it possible to set the objectMapper property of the MappingJacksonJsonView?

Thanks in advance.

JSON Serialization of deeper relationsship's

Hi Tatu,

sorry to re-open this issue again but it seems you haven't seen my post.

Your lib works like a charm, but only for the first level of association for me.

Using

  • Spring 3.0.5
  • Jackson 1.8.5
  • and Version 0.7.0 of your lib

When I select content from DB like this

criteria.
createAlias("matCountry","seizure_country").        
setFetchMode("matCountry", FetchMode.EAGER).
createAlias("seizure_country.matCountryI18ns","seizure_country_translation").
setFetchMode("matCountryI18ns", FetchMode.EAGER).
add(Restrictions.eq("seizure_country_translation.matLanguageCode", "de"));

List<Seizure> seizures = getHibernateTemplate().findByCriteria(criteria);

The SQL for it gets correctly created

SELECT this_.id                         AS id36_2_,
       this_.mat_country_id             AS mat2_36_2_,
       _created                         AS column3_36_2_,
       _created_by                      AS column4_36_2_,
       _modified                        AS column5_36_2_,
       _modified_by                     AS column6_36_2_,
       this_.date_of_seizure            AS date7_36_2_,
       this_.date_of_report             AS date8_36_2_,
       this_.seizure_ref_number         AS seizure9_36_2_,
       this_.class_nature_of_seizure_id AS class10_36_2_,
       _class_workflow_status_id        AS column11_36_2_,
       seizure_co1_.id                  AS id9_0_,
       seizure_co1_.code                AS code9_0_,
       seizure_co1_.iso_alpha_2_code    AS iso3_9_0_,
       seizure_co2_.id                  AS id37_1_,
       seizure_co2_.mat_country_id      AS mat2_37_1_,
       seizure_co2_.title               AS title37_1_,
       seizure_co2_.mat_language_code   AS mat4_37_1_
FROM   incbszdb.seizure this_
       INNER JOIN incbszdb.mat_country seizure_co1_
         ON this_.mat_country_id = seizure_co1_.id
       INNER JOIN incbszdb.mat_country_i18n seizure_co2_
         ON seizure_co1_.id = seizure_co2_.mat_country_id
WHERE  seizure_co2_.mat_language_code = ?  

See following POJOs

Parent:

@Entity
@Table(name = "seizure", catalog = "incbszdb")
public class Seizure implements java.io.Serializable {
  ...
  private MatCountry matCountry;
  ...
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "mat_country_id", nullable = false)
  public MatCountry getMatCountry() {
    return this.matCountry;
  }

  public void setMatCountry(MatCountry matCountry) {
    this.matCountry = matCountry;
  }
  ...
}

Parent => Child 1

@Entity
@Table(name = "mat_country", catalog = "incbszdb")
public class MatCountry implements java.io.Serializable {
   ....
   private Set<MatCountryI18n> matCountryI18ns = new HashSet<MatCountryI18n>(0);
   ....
   @OneToMany(fetch = FetchType.LAZY, mappedBy = "matCountry")
   public Set<MatCountryI18n> getMatCountryI18ns() {
    return this.matCountryI18ns;
   }

   public void setMatCountryI18ns(Set<MatCountryI18n> matCountryI18ns) {
    this.matCountryI18ns = matCountryI18ns;
   }   
   ....
}

Parent => Child1 => Child 2

@Entity
@Table(name = "mat_country_i18n", catalog = "incbszdb")
public class MatCountryI18n implements java.io.Serializable {
   ...
}

See returned JSON

{
  "data": [{
    "id": 1,
    "matCountry": {
      "id": 1,
      "code": "de",
      "shipmentRouteTransits": null,
      "isoAlpha2Code": "22",
      "shipmentRoutesForDestinationMatCountryId": null,
      "shipmentRoutesForOriginMatCountryId": null,
      "matInstitutions": null,
      "matCountryI18ns": null,
      "seizures": null
    },
    "seizureClassServices": null,
    "seizureI18n": null,
    "created": "2011-06-27T14:53:01.000+0000",
    "createdBy": 0,
    "dateOfSeizure": "2011-06-27",
    "dateOfReport": "2011-06-27",
    "seizureRefNumber": "1234",
    "shipmentRoutes": null,
    "seizureDocuments": null,
    "seizureClassSourceOfInformations": null,
    "seizureClassReasons": null,
    "seizureMatInstitutions": null,
    "seizureClassMethodOfDiversions": null,
    "substanceIdentifieds": null,
    "seizureClassWorkflowStatuses": null,
    "seizureClassNatureOfSeizures": null
  }]
}

I'm using ContentNegotiatingViewResolver

<bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="mediaTypes">
            <map>
                <entry key="html" value="text/html" />
                <entry key="json" value="application/json" />
            </map>
        </property>
        <property name="viewResolvers">
            <list>
                <bean id="viewResolver"
                    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                    <property name="prefix" value="/WEB-INF/assets/" />
                    <property name="suffix" value=".jsp" />
                </bean>
            </list>
        </property>
        <property name="defaultViews">
            <list>
                <bean
                    class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
                    <property name="prefixJson" value="false" />
                    <property name="objectMapper" ref="jacksonObjectMapper" />
                </bean>
            </list>
        </property>
    </bean>

and AnnotationMethodHandlerAdapter

    <bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean
                    class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                    <property name="objectMapper" ref="jacksonObjectMapper" />
                </bean>
            </list>
        </property>
    </bean>

If you need any further clarification please tell.

NullPointer when using SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS = true

When using:
SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS = true
Jackson throws a NullPointerException when trying to serialize ManyToOne proxies.

In fact this is thrown at:
com.fasterxml.jackson.datatype.hibernate4.HibernateProxySerializer.findProxied(HibernateProxy proxy)
when it tries to retrieve session, because session is closed, and proxy.getHibernateLazyInitializer().getSession() should return null (as javadoc says).

If I'm not wrong session should be null, and this is why we use jackson-module-hibernate. I think there should be another option to load the name of the attribute other than looking for it through the session, it makes no sense to me. If ID value is still loaded, why do we need the session to retrieve the ID property name?

Probably I'm missing lot of things anyway. But making some introspection in the proxy object and retrieving property name annotated with javax.persistence.Id should do the trick instead of asking the name through the session (session.getFactory().getIdentifierPropertyName(init.getEntityName()), looks like a simple thing (but as i said I'm probably wrong).

Just disabling SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS let jackson-module-hibernate serialize it as expected

(Sorry for english)

@Transient annotations are not being serialized

I'm configuring HibernateObjectAwareMapper in the following way, but @transient fields are not being serialized after updating to version 2.3.3.

public HibernateAwareObjectMapper() {
        Hibernate4Module hm = new Hibernate4Module();
        hm.disable(Hibernate4Module.Feature.USE_TRANSIENT_ANNOTATION);
        registerModule(hm);
    }

ConversionNotSupportedException

Can someone at least provide the imports used in the example at the bottom of the homepage/doc page ?

I get the following when I try to follow it:

 Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'com.xxx.ql.json.HibernateAwareObjectMapper' to required type 'org.codehaus.jackson.map.ObjectMapper' for property 'objectMapper'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [com.funnelscope.ql.json.HibernateAwareObjectMapper] to required type [org.codehaus.jackson.map.ObjectMapper] for property 'objectMapper': no matching editors or conversion strategy found
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:485) [spring-beans-3.1.0.RELEASE.jar:3.1.0.RELEASE]

here my object mapper

package com.xxx.ql.json;

import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;
import org.springframework.stereotype.Service;

/**
 *
 */
@Service
class HibernateAwareObjectMapper extends ObjectMapper {
 public HibernateAwareObjectMapper() {
    Module hm = new Hibernate4Module();

    super.registerModule(hm);
    super.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
 }
}

my config..

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
      <list>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
            <property name="objectMapper">
                    <bean class="com.xxx.ql.json.HibernateAwareObjectMapper"/>
                  </property>
        </bean>
      </list>
    </property>
</bean>

HibernateProxySerializer never called

I was able to successfully use this, but I had to make a code change to do it. I would fork this and submit a patch but I don't have git installed yet and don't have time at the moment.

The change was in HibernateSerializers from this:
if (HibernateProxy.class.isAssignableFrom(raw)) {
// return new HibernateProxySerializer(type, config);
// return new PersistentCollectionSerializer(type, isEnabled(Feature.FORCE_LAZY_LOADING));
}

to this:
if (HibernateProxy.class.isAssignableFrom(raw)) {
return new HibernateProxySerializer( isEnabled(Feature.FORCE_LAZY_LOADING));
// return new PersistentCollectionSerializer(type, isEnabled(Feature.FORCE_LAZY_LOADING));
}

Annie

Still getting LazyInitialization Exception

Hi ,

I have integrated jackson-datatype-hibernate version 2.3.3 into my application. I am using spring MVC 3.2 and hibernate 3.6.

My Controller returns a User Object that has few String Fields , and collections defined in it .

The ManyToMany relationships on the collections in User (hibernate Entity) have been mentioned to use lazy fetch stratergy.

My expectation was using this module jackson can serialize the entire user object including the collections while generating the JSON, But instead I am still getting LazyInitializtion Exception.

Any help would be appreciated.

Regards,
Ravi

Hibernate session end before serialization

Hello,

I have a Jersey 1.x/Spring 4/Hibernate 4 application and i'm trying to serialize Entity that is managed by Hibernate. The serialisation is done by a JsonSerializer but when i trying to access to lazy-loaded properties, i have an exception because the Hibernate Session is closed.

@Path("api/contexts")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Component
public class ContextsResource {

    @GET
    @Transactionnal
    @JsonView(ContextViews.Display.class)
    public List<ContextAccess> getList() {
            return contextService.getList()
    }
}
public class ContextAccessSerializer extends JsonSerializer<ContextAccess> {
  // try to access to lazy-loaded properties of a ContextAccess object
}

[...]

@JsonSerialize(using = ContextAccessSerializer.class)
public class ContextAccess {}

However i have the right Maven dependencies (version 2.4.3)

             <dependency>
                <groupId>com.fasterxml.jackson.jaxrs</groupId>
                <artifactId>jackson-jaxrs-json-provider</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.datatype</groupId>
                <artifactId>jackson-datatype-hibernate4</artifactId>
                <version>${jackson.version}</version>
            </dependency>

And my config include the Hibernate4Module

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonConfig implements ContextResolver<ObjectMapper> {

    private final ObjectMapper objectMapper;

    public JacksonConfig() {
        objectMapper = new ObjectMapper();
        // Date format (Example : Mon, 06 Oct 2014 11:41:17 CEST)
        SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        objectMapper.setDateFormat(dateFormat);
        // Ignore Null Fields Globally
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // allow serialization of lazy collections
        objectMapper.registerModule(new Hibernate4Module());
    }

    @Override
    public ObjectMapper getContext(Class<?> objectType) {
        return objectMapper;
    }

}

did i miss something or Hibernate4Module doesn't support this use case?

Problem Using @JsonTypeInfo with Hibernate4Module

Hibernate4Module with FORCE_LAZY_LOADING=false does not prevent lazy loading when using a parent class with @JsonTypeInfo (and related annotations)

This Maven project demonstrates the issue, instructions are in the comment of AppTest.java:

https://www.dropbox.com/s/3smkisfpl2dppf2/jhp.tgz

Also, here is my original email describing the issue:

Hi
I have been writing a REST service using CXF+Jackson and have hit a bit of a road block. The service method I'm having trouble with loads entities from hibernate 4 to serialize and return, and is as follows:
I have parent class, ModeratedContent, and it has two child classes, Review and Comment.
Another class, Product, contains a lazily-loaded list of Reviews. The lazy-loading initially gave me trouble when serializing as it would try to load all the Reviews with no hibernate session available. After some research I got around this by registering Hibernate4Module with FORCE_LAZY_LOADING=false to my ObjectMapper, now when it serializes it just ignores non loaded LAZY lists. Great!
My problem now is that I am implementing type-negotiation, by adding the following annotations:

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="@jsdtype", defaultImpl=Comment.class)
@JsonSubTypes({
@type(value=Comment.class, name="comment"),
@type(value=Review.class, name="review")
})
public abstract class ModeratedContent {
...

With these annotations I am now getting the LazyInitializationException again on the Product.reviews relationship! It seems like @JsonTypeInfo does not play well with Hibernate4Module.

Cheers!

where i set HibernateModule.Feature.FORCE_LAZY_LOADING

plz help me where HibernateModule.Feature.FORCE_LAZY_LOADING set
is set like this but not work
i use spring 3.1.1
public class HibernateAwareObjectMapper extends ObjectMapper {
public HibernateAwareObjectMapper() {
HibernateModule hm = new HibernateModule();
hm.configure(com.fasterxml.jackson.module.hibernate.HibernateModule.Feature.FORCE_LAZY_LOADING, true);
registerModule(hm);
configure(Feature.FAIL_ON_EMPTY_BEANS, false);
HibernateModule.Feature.
}

public void setPrettyPrint(boolean prettyPrint) {
    configure(Feature.INDENT_OUTPUT, prettyPrint);
}

}

Add a per-property annotation to force (or not) loading of property value

Currently there exists global setting of 'HibernateModule.Feature.FORCE_LAZY_LOADING' which can be used to ensure that data marked to be lazily loaded is actually forced to be loaded when serializing.
But there are cases where it would be better to allow defining per-property overrides, instead of a global setting.

Registered hibernateModule lead to 'NON_EMPTY' failure

public class Mock
{
    private Long id;
    private String name;
    private Set<String> mocks = Sets.newHashSet();
}

new ObjectMapper().registerModule(new Hibernate3Module()).setSerializationInclusion(Include.NON_EMPTY).writeValueAsString(mock)

output

{"mocks":[]}

Feature.USE_TRANSIENT_ANNOTATION does not work with current jackson-data

since version 2.0 of jackson-data the isIgnorable...() methods of AnnotationIntrospector are replaced with hasIgnoreMarker(). Therefore Feature.USE_TRANSIENT_ANNOTATION does not work.

In class HibernateAnnotationIntrospector the isIgnorable...() methods should be replaced by:

@Override
public boolean hasIgnoreMarker(AnnotatedMember m) {
    return _cfgCheckTransient && m.hasAnnotation(Transient.class);
}

LazyInitializationException when wrapped in unmodifiableCollection

I just spent a couple hours tracking a problem in my app in which I got the infamous LazyInitializationException in one of my relations.
Finally i discovered that the problem was that the getter for the collection was wrapping the actual collection in an unmodifiable collection in order to "protect" the developer from trying to modify the relationship through it, like this:

public Set<Foobar> getFoobars() {
    return Collections.unmodifiableSet(foobars);
}

Would it be possible/reasonable to add a feature to handle this case and avoid trying to navigate the relationship?

ObjectMapper should detect if the session is already opened

Please refer to stackoverflow

When spring integration test is annotated with @transactional, persists a child entity and then calls a controller to return the parent entity then exception is thrown. It happens because the child entity is stored in a first session opened by @transactional and object mapper tries to open another session to convert the parent entity to json, so the child entity appears in two sessions which lead to the exception.

Hibernate4Module and custom Map Serializer / Deserializer issue

Hi !

First of all, excuse my poor / bad english, and excuse me if i'm not posting in the proper place.

I may have found a problem using Hibernate4Module.

I'm not sure it is revelant for you, but I'm using RESTeasy on a JBOSS 7.1 server.

I have a class I need to serialize into JSON with this map and annotations :


@JsonSerialize(keyUsing = EnvironmentalFactorIdSerializer.class, keyAs = EnvironmentalFactorId.class)
@JsonDeserialize(keyUsing = EnvironmentalFactorIdDeserializer.class, keyAs = EnvironmentalFactorId.class)
private Map<EnvironmentalFactorId, Double> envFactModulationCoefficent;

EnvironmentalFactorId is the key class containing these attributes:


public class EnvironmentalFactorId implements Serializable {
public String factor;
public String zoneName;
    // Geters and Seters are define too
}

And I create this simple serializer and deserializer :


public class EnvironmentalFactorIdSerializer extends StdSerializer<EnvironmentalFactorId>
{

protected EnvironmentalFactorIdSerializer() {
    super(EnvironmentalFactorId.class);
}

public void serialize(EnvironmentalFactorId efi, JsonGenerator jgen,
        SerializerProvider provider) throws IOException,
        JsonGenerationException {
    ObjectMapper mapper = new HibernateAwareObjectMapper();
    jgen.writeFieldName(mapper.writeValueAsString(efi));
   }
}

public class EnvironmentalFactorIdDeserializer extends StdKeyDeserializer {
public EnvironmentalFactorIdDeserializer() {
    super(EnvironmentalFactorId.class);
}

@Override
public EnvironmentalFactorId _parse(String key, DeserializationContext ctxt)
        throws JsonMappingException {
    ObjectMapper mapper = new HibernateAwareObjectMapper();
    try {
        return mapper.readValue(key, EnvironmentalFactorId.class);
    } catch (Exception e) {
        throw ctxt.weirdKeyException(_keyClass, key, e.getMessage());
    }
}
}

The issue appears when I use an ObjectMapper with an Hibernate4Module registered in it, the serialization process seems to ignore the previous annotations (I put multiples breakpoints in the serializer and deserializer). But if I use the standard ObjectMapper provided by Jackson, the execution success.

The mapper I use:

public class HibernateAwareObjectMapper extends ObjectMapper
{
public HibernateAwareObjectMapper() {
  registerModule(new Hibernate4Module());
}
}

I may have missunderstood something with the custom map serialization / deserialization process, let me know about it.

Moreover, I may have forgotten some details you need to understand the problem, here again, let me know about it, and I'll try to give you the informations back.

Finally, I want to say that the Jackson Hibernate Module save my life about the Lazy Initialization Exception, it's a great job you did here !

Best Regards!

Lazy associations mapped as null values even if JsonInclude.NON_NULL is present

This module rocks! But I think we are missing a feature to actually not include the association at all in the response. I have the module setup and my mapper is using mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

But all the lazy associations are displayed in my json as null values. The other nulls I have (single table columns) are not serialized but the associations are displayed.

Fields annotated with @JsonManagedReference and @JsonBackReference throw JsonMappingException

Using FasterXML-jackson-module-hibernate-a2424df we get the following exception:

org.codehaus.jackson.map.JsonMappingException: PersitentCollection does not have serializer set (through reference chain: my.Wrapper["data"]->java.util.ArrayList[0]->my.Content["parent"]->my.Parent["child"])
com.fasterxml.jackson.module.hibernate.PersistentCollectionSerializer.serialize(PersistentCollectionSerializer.java:100)
com.fasterxml.jackson.module.hibernate.PersistentCollectionSerializer.serialize(PersistentCollectionSerializer.java:1)
org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:430)
org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142)
org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:430)
org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142)
org.codehaus.jackson.map.ser.ContainerSerializers$IndexedListSerializer.serializeContents(ContainerSerializers.java:304)
org.codehaus.jackson.map.ser.ContainerSerializers$IndexedListSerializer.serializeContents(ContainerSerializers.java:254)
org.codehaus.jackson.map.ser.ContainerSerializers$AsArraySerializer.serialize(ContainerSerializers.java:142)
org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:430)
org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142)
org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:606)
org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:280)
org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:1345)
org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.writeInternal(MappingJacksonHttpMessageConverter.java:153)

Basically, we have a circular reference between "parent" and "child" which we have annotated using
@JsonManagedReference and @JsonBackReference. so that we don't run into a stack overflow trying to
dereference these.

I can "fix" this issue by removing the code that throws a JsonMappingException in PersistentCollectionSerializer and replacing it with a "defaultSerializeNull()" call. I'm not sure if this is the correct behavior but it solves our immediate problem.
The code change was:

---- Original ----
if (_serializer == null) { // sanity check...
throw new JsonMappingException("PersitentCollection does not have serializer set");
}

---- Changed ----
if (_serializer == null) { // sanity check...
provider.defaultSerializeNull(jgen);
} else {
_serializer.serialize(value, jgen, provider);
}

Classes are not added to 2.3.0-rc1 jar

Version 2.3.0-rc1 jar downloaded from maven central repository is only 5KB and does not contain any binary under package com.fasterxml.jackson.datatype.hibernate3. Cloning latest snapshot and building locally also results in the same empty folder

@JsonTypeInfo results in differing type information used for locating serializer

Summary:
This has to do with difference between static type (Set) and runtime type (PersistentSet).

Use of @JsonTypeInfo forces use of static type for container types, because type serializer (thing that handles mapping of type ids) needs to be linked. But at that point actual runtime is not known.

As a result, type information used for locating serializer differs.

Discussion for this issue can be found here:
http://jackson-users.ning.com/forum/topics/jackson-module-hibernate-serializing-lazy-properties

Feature.SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS customise generated name

It would be good if Feature.SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS would let you customise the generated name, or at least use the name from the java bean.

Currently it is serializing using full package and class name:

"client":{"com.test.domain.Client":1}

I want it to use the id instead (which is the name of the attribute in the hibernate entity):

"client":{"id":1}

Maybe there is a way around this but I can't find any.

org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: could not initialize proxy - no Session

spring 3.2.0.M2 (3.1.2 also tryed)
spring-data-jpa 1.1.0.RELEASE
hibernate 4.1.7.Final
jackson-module-hibernate 2.0.2 (2.0.0 also tryed)

org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->smind.core.domain.ContentLink["tags"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->smind.core.domain.ContentLink["tags"])
    org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.writeInternal(MappingJackson2HttpMessageConverter.java:196)
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:179)
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:149)
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:90)
    org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:157)
    org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:69)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:717)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:660)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:804)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:789)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:770)

Initialize (Java Config):

    @Bean
    public AnnotationMethodHandlerAdapter adapter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(new HibernateAwareObjectMapper());

        AnnotationMethodHandlerAdapter adapter = new AnnotationMethodHandlerAdapter();
        adapter.setMessageConverters(new HttpMessageConverter[] { converter });

        return adapter;
    }

HibernateAwareObjectMapper:

package smind.web.rest.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;

public class HibernateAwareObjectMapper extends ObjectMapper {

    public HibernateAwareObjectMapper() {
        Hibernate4Module hm = new Hibernate4Module();
        hm.configure(Hibernate4Module.Feature.FORCE_LAZY_LOADING, false);
        registerModule(hm);
        configure(SerializationFeature.INDENT_OUTPUT, true);
    }

}

ContentLink:

package smind.core.domain;

import javax.persistence.Column;
import javax.persistence.Entity;

@Entity
public class ContentLink extends AbstractContent {

    private static final long serialVersionUID = -6690443064244655726L;

    private String note;

    private String url;

    public ContentLink() {
        super();
    }

    @Column(length = 2048)
    public String getNote() {
        return note;
    }

    @Column(length = 8192, nullable = false)
    public String getUrl() {
        return url;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public void setUrl(String url) {
        this.url = url;
    }

}

AbstractContent ("tags" marked as "lazy"):

package smind.core.domain;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class AbstractContent extends AbstractDomain {

    private static final long serialVersionUID = 5533781610346361703L;

    private List tags;

    private String title;

    private User user;

    @ManyToMany(mappedBy = "contents", fetch = FetchType.LAZY)
    public List getTags() {
        return tags;
    }

    @Column(length = 512, nullable = false)
    public String getTitle() {
        return title;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    public User getUser() {
        return user;
    }

    public void setTags(List tags) {
        this.tags = tags;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setUser(User user) {
        this.user = user;
    }

}

Handle serialization of lazy-loaded properties

(note: moved from [http://jira.codehaus.org/browse/JACKSON-276])

As one of most obvious special cases with Hibernate, there should be support for properly handling serialization (or lack thereof) of lazy-loaded properties such as collections.

Should ignore org.hibernate.bytecode.internal.javassist.FieldHandled.getFieldHandler()

When using bytecode enhancement, Hibernate classes get a new field, "fieldHandler" from the org.hibernate.bytecode.internal.javassist.FieldHandled interface. You can see how to set up bytecode enhancement and see what the generated code looks like at http://vladmihalcea.com/2014/09/08/hibernate-bytecode-enhancement/

This field should not be serialized/deserialized by Jackson.

Here's the module I've made to workaround this:

private static class FiledHandledModule extends SimpleModule {
    private abstract class FieldHandledMixIn implements FieldHandled {

        @Override
        @JsonIgnore
        public abstract void setFieldHandler(FieldHandler handler);

        @Override
        @JsonIgnore
        public abstract  FieldHandler getFieldHandler();

    }

    @Override
    public void setupModule(SetupContext context) {
        super.setupModule(context);
        context.setMixInAnnotations(FieldHandled.class, FieldHandledMixIn.class);
    }

}

com.fasterxml.jackson.databind.JsonMappingException: [no message for java.lang.NullPointerException]

Hi,

Recently I used the original Jackson ObjectMapper and I have Map with Array of Object as value. The problem occurred when using this module is when one of the Object value is null. For example:

    Map<String, FilterWhereClause[]> filteredColumns = new HashMap<>();
    filteredColumns.put("name1", new FilterWhereClause[]{
        new FilterWhereClause("name1", "=", "name1_0"),
        null
    });

and then write the value like the previous one:

objectMapper.writeValueAsString(filteredColumns);

and I got JsonMappingException like this:

SEVERE: null
com.fasterxml.jackson.databind.JsonMappingException: [no message for java.lang.NullPointerException]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:129)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:2718)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:2210)

I probably missing some configuration on how to handle this?

Thanks in advance!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.