glassfish
  1. glassfish
  2. GLASSFISH-20815

Wrong JSON string produced when calling single instance of object will a list<T> of same object is correctly formated.

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 4.0_b89_RC5
    • Fix Version/s: None
    • Component/s: json
    • Labels:
      None
    • Environment:

      Win2003R2 SP2 jdk1.7.0_25 eclipselinks, com.fasterXML V2.2.3 IDE eclipse Juno

      Description

      Wrong JSON string produced when calling single instance of object will a list<T> of same object is correctly formated. if I look at the stack trace (see below) there is a big difference between both methodes. There are no exception in the log.

      =============== CORRECT FORMAT =====================
      c:>curl -H "Accept:application/json" http://localhost:8080/emberGF4/rest/customers

      {"customers":[

      {"id":1,"first_name":"F1","last_name":"L1","order_ids" : [1]}

      ,

      {"id":2,"first_name":"F2","last_name":"L2","order_ids":[]}

      ]}

      produced by:
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public Customers get(@QueryParam("ids[]") List ids) {
      if (ids != null && !ids.isEmpty())

      { return new Customers(manager.findByIds(ids)); }

      return new Customers(manager.findAll());
      }

      @JsonRootName("customers")
      class Customers extends ArrayList<Customer> {
      private static final long serialVersionUID = 1L;

      public Customers(Collection<? extends Customer> c)

      { addAll(c); }

      }

      =============== Wrong Format =====================
      c:>curl -H "Accept:application/json" http://localhost:8080/emberGF4/rest/customers/2

      {"firstName":"F2","id":2,"lastName":"L2","orders":[]}

      On single object the @JsonRootName("customer") is missing and @JsonIdentityReference(alwaysAsId = true) @JsonProperty("order_ids")

      produced by:
      @Path("/

      {id}

      ")
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public Customer get(@PathParam("id") Long id) {
      Customer c = manager.find(id);
      return c;
      }

      ================= Customer =========================
      package ember.sample.entity;

      import java.util.Set;
      import java.util.TreeSet;

      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.GeneratedValue;
      import javax.persistence.GenerationType;
      import javax.persistence.Id;
      import javax.persistence.OneToMany;
      import javax.persistence.Table;
      import javax.validation.constraints.Size;

      import org.hibernate.validator.constraints.NotEmpty;

      import com.fasterxml.jackson.annotation.JsonIdentityInfo;
      import com.fasterxml.jackson.annotation.JsonIdentityReference;
      import com.fasterxml.jackson.annotation.JsonProperty;
      import com.fasterxml.jackson.annotation.JsonRootName;
      import com.fasterxml.jackson.annotation.ObjectIdGenerators;

      @Entity
      @Table
      @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
      @JsonRootName("customer")
      public class Customer {

      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long id;

      @Column(length = 24)
      @Size(max = 24)
      @NotEmpty
      @JsonProperty("first_name")
      private String firstName;

      @Column(length = 24)
      @Size(max = 24)
      @NotEmpty
      @JsonProperty("last_name")
      private String lastName;

      @OneToMany(mappedBy = "customer")
      @JsonIdentityReference(alwaysAsId = true)
      @JsonProperty("order_ids")
      private Set<CustomerOrder> orders = new TreeSet<>();

      public Customer() {
      }

      public Customer(Long id) {
      super();
      this.id = id;
      }

      public Long getId() {
      return id;
      }

      public void setId(Long id) {
      this.id = id;
      }

      public String getFirstName() {
      return firstName;
      }

      public void setFirstName(String firstName) {
      this.firstName = firstName;
      }

      public String getLastName() {
      return lastName;
      }

      public void setLastName(String lastName) {
      this.lastName = lastName;
      }

      public Set<CustomerOrder> getOrders() {
      return orders;
      }

      public void setOrders(Set<CustomerOrder> orders) {
      this.orders = orders;
      }
      }

      ================= ApplicationConfig =========================
      @ApplicationPath("rest/*")
      public class ApplicationConfig extends Application {
      @Override
      public Set<Class<?>> getClasses()

      { Set<Class<?>> resources = new java.util.HashSet<Class<?>>(); // following code can be used to customize Jersey 2.0 JSON provider: //features //this we will register Jackson JSON providers resources.add(org.glassfish.jersey.jackson.JacksonFeature.class); return resources; }

      @Override
      public Set<Object> getSingletons()

      { return Collections.emptySet(); }

      @Override
      public Map<String, Object> getProperties()

      { Map<String, Object> properties = new HashMap<>(); properties.put("jersey.config.property.packages","org.hsqldb,com.fasterxml.jackson.jaxrs.json,com.fasterxml.jackson.dataformat,com.fasterxml.jackson.datatype,ember.sample.rest"); properties.put("javax.xml.bind.context.factory","org.eclipse.persistence.jaxb.JAXBContextFactory"); return properties; }

      }

      ================= ObjectMapperProvider =========================
      @Provider
      public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {

      private ObjectMapper objectMapper;

      public ObjectMapperProvider()

      { objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true); }

      @Override
      public ObjectMapper getContext(@SuppressWarnings("rawtypes") Class type)

      { return objectMapper; }

      }

      ================ POM.XML ================================
      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>

      <groupId>emberGF4mvn</groupId>
      <artifactId>emberGF4mvn</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>war</packaging>

      <name>emberGF4mvn</name>

      <properties>
      <endorsed.dir>$

      {project.build.directory}

      /endorsed</endorsed.dir>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>

      <dependencies>
      <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-web-api</artifactId>
      <version>7.0</version>
      <scope>provided</scope>
      </dependency>
      <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.2.3</version>
      </dependency>
      <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.2.3</version>
      </dependency>
      <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>5.0.0.Final</version>
      </dependency>
      <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.5</version>
      </dependency>
      <dependency>
      <groupId>org.hsqldb</groupId>
      <artifactId>hsqldb</artifactId>
      <version>2.3.0</version>
      </dependency>
      <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.2.3</version>
      </dependency>
      <dependency>
      <groupId>com.fasterxml.jackson.jaxrs</groupId>
      <artifactId>jackson-jaxrs-json-provider</artifactId>
      <version>2.2.3</version>
      </dependency>
      <dependency>
      <groupId>com.fasterxml.jackson.jaxrs</groupId>
      <artifactId>jackson-jaxrs-base</artifactId>
      <version>2.2.3</version>
      </dependency>
      <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>4.2.5.Final</version>
      </dependency>
      <dependency>
      <groupId>org.hibernate.javax.persistence</groupId>
      <artifactId>hibernate-jpa-2.0-api</artifactId>
      <version>1.0.1.Final</version>
      </dependency>
      <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>4.2.5.Final</version>
      </dependency>
      <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-envers</artifactId>
      <version>4.2.5.Final</version>
      </dependency>
      </dependencies>

      <build>
      <plugins>
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
      <source>1.7</source>
      <target>1.7</target>
      <compilerArguments>
      <endorseddirs>$

      {endorsed.dir}</endorseddirs>
      </compilerArguments>
      </configuration>
      </plugin>
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-war-plugin</artifactId>
      <version>2.3</version>
      <configuration>
      <failOnMissingWebXml>false</failOnMissingWebXml>
      </configuration>
      </plugin>
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <version>2.6</version>
      <executions>
      <execution>
      <phase>validate</phase>
      <goals>
      <goal>copy</goal>
      </goals>
      <configuration>
      <outputDirectory>${endorsed.dir}

      </outputDirectory>
      <silent>true</silent>
      <artifactItems>
      <artifactItem>
      <groupId>javax</groupId>
      <artifactId>javaee-endorsed-api</artifactId>
      <version>7.0</version>
      <type>jar</type>
      </artifactItem>
      </artifactItems>
      </configuration>
      </execution>
      </executions>
      </plugin>
      </plugins>
      </build>

      </project>

      ============================== persistence.XML ======================
      <?xml version="1.0" encoding="UTF-8"?>
      <persistence version="2.0"
      xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
      <!-- GLASSFISH4 when using JTA via CDI to work run following command
      asadmin set configs.config.server-config.cdi-service.enable-implicit-cdi=false
      -->
      <persistence-unit name="pu" transaction-type="RESOURCE_LOCAL">

      <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
      <class>ember.sample.entity.Customer</class>
      <class>ember.sample.entity.CustomerOrder</class>
      <class>ember.sample.entity.OrderItem</class>
      <class>ember.sample.entity.Product</class>

      <properties>
      <property name="eclipselink.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
      <property name="eclipselink.jdbc.url" value="jdbc:hsqldb:mem:test"/>
      <property name="eclipselink.jdbc.user" value="sa"/>
      <property name="eclipselink.jdbc.password" value=""/>
      <property name="eclipselink.target-database"
      value="org.eclipse.persistence.platform.database.HSQLPlatform"/>
      <property name="eclipselink.logging.level" value="OFF"/>
      <property name="eclipselink.orm.throw.exceptions" value="true"/>

      <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
      <property name="eclipselink.ddl-generation.output-mode" value="database"/>
      </properties>
      </persistence-unit>
      </persistence>

      ================== Stack Trace LIST methode ============
      CustomerService.get(List<Long>) line: 61
      NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not
      available [native method]
      NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57
      DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
      Method.invoke(Object, Object...) line: 601
      ContextBeanInstance<T>(AbstractBeanInstance).invoke(Object, Method,
      Object...) line: 46
      ProxyMethodHandler.invoke(Object, Method, Method, Object[]) line: 101
      CustomerService$Proxy$_$$_WeldClientProxy.get(List) line: not available
      NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: notavailable [native method]

      ================== Stack Trace one instance methode ============
      CustomerService.get(Long) line: 69
      CustomerService$Proxy$_$$_WeldClientProxy.get(Long) line: not available
      NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]

        Activity

        Hide
        christBe added a comment -

        Seems problem is with jackson the 2 versions of com.FasterXML and org.codehaus.

        Got it (almost 100%) working with own Feature class

        public class FasterXmlJacksonFeature implements Feature {

        @Override
        public boolean configure(final FeatureContext context)

        { // >>> CommonProperties causes CDI WELD ERROR! //final String disableMoxy = CommonProperties.MOXY_JSON_FEATURE_DISABLE + '.' + context.getConfiguration().getRuntimeType().name().toLowerCase(); //final String disableJSON = CommonProperties.JSON_PROCESSING_FEATURE_DISABLE + '.' + context.getConfiguration().getRuntimeType().name().toLowerCase(); final String disableMoxy = "jersey.config.disableMoxyJson" + '.' + context.getConfiguration().getRuntimeType().name().toLowerCase(); final String disableJSON = "jersey.config.disableJsonProcessing" + '.' + context.getConfiguration().getRuntimeType().name().toLowerCase(); context.property(disableMoxy, true); context.property(disableJSON, true); //com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider or JacksonJaxbJsonProvider?? context.register(com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class); return true; }

        }

        ApplicationConfig add resources.add(ember.sample.rest.provider.FasterXmlJacksonFeature.class); to getClasses

        curl -H "Accept:application/json" http://localhost:8080/emberGF4/rest/customers
        {"customers":[

        {"id":51,"first_name":"F1","last_name":"L1","order_ids":[551,451]}

        ,

        {"id":151,"first_name":"F2","last_name":"L2","order_ids":[]}

        ]}
        curl -H "Accept:application/json" http://localhost:8080/emberGF4/rest/customers/51
        {"customer":{"id":51,"first_name":"F1","last_name":"L1","order_ids":[551,451]}}

        The almost comes from GF4 problems

        • on re-deploy parsing throw errors so you need to restart GF4 for com.fasterXML to work again
        • CDI is not working because bundle dependencies
        Show
        christBe added a comment - Seems problem is with jackson the 2 versions of com.FasterXML and org.codehaus. Got it (almost 100%) working with own Feature class public class FasterXmlJacksonFeature implements Feature { @Override public boolean configure(final FeatureContext context) { // >>> CommonProperties causes CDI WELD ERROR! //final String disableMoxy = CommonProperties.MOXY_JSON_FEATURE_DISABLE + '.' + context.getConfiguration().getRuntimeType().name().toLowerCase(); //final String disableJSON = CommonProperties.JSON_PROCESSING_FEATURE_DISABLE + '.' + context.getConfiguration().getRuntimeType().name().toLowerCase(); final String disableMoxy = "jersey.config.disableMoxyJson" + '.' + context.getConfiguration().getRuntimeType().name().toLowerCase(); final String disableJSON = "jersey.config.disableJsonProcessing" + '.' + context.getConfiguration().getRuntimeType().name().toLowerCase(); context.property(disableMoxy, true); context.property(disableJSON, true); //com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider or JacksonJaxbJsonProvider?? context.register(com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class); return true; } } ApplicationConfig add resources.add(ember.sample.rest.provider.FasterXmlJacksonFeature.class); to getClasses curl -H "Accept:application/json" http://localhost:8080/emberGF4/rest/customers {"customers":[ {"id":51,"first_name":"F1","last_name":"L1","order_ids":[551,451]} , {"id":151,"first_name":"F2","last_name":"L2","order_ids":[]} ]} curl -H "Accept:application/json" http://localhost:8080/emberGF4/rest/customers/51 {"customer":{"id":51,"first_name":"F1","last_name":"L1","order_ids": [551,451] }} The almost comes from GF4 problems on re-deploy parsing throw errors so you need to restart GF4 for com.fasterXML to work again CDI is not working because bundle dependencies

          People

          • Assignee:
            michael.y.chen
            Reporter:
            christBe
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: