Hot questions for Using GlassFish in jax rs

Question:

Following up on this SO thread, my question is whether I'm doing something fundamentally wrong here:

Using GlassFish 4.1, I'm trying to write a MessageBodyReader that has a constructor like this:

package com.acme;

import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.Providers;
import javax.ws.rs.Consumes;

@Provider
@Consumes( "application/xml" )
public class MyMessageBodyReader implements MessageBodyReader<Object> {
   public MyMessageBodyReader(@Context Providers ps) {
      // try to do something with ps here
      // e.g. pass to a superclass constructor,
      // as required by the solution in the other thread
   }

   [...] // implemented interface methods
}

But whatever I do wrt surrounding configuration, I always get a sequence of these exceptions:

2016-06-07T17:19:28.484+0200|WARN: The following warnings have been detected: WARNING: Unknown HK2 failure detected:
MultiException stack 1 of 1
org.jboss.weld.exceptions.CreationException: WELD-001530: Cannot produce an instance of class com.acme.MyMessageBodyReader.
    at org.jboss.weld.injection.producer.NonProducibleInjectionTarget.produce(NonProducibleInjectionTarget.java:55)
    at org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider$CdiFactory$2.getInstance(CdiComponentProvider.java:242)
    at org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider$CdiFactory.provide(CdiComponentProvider.java:189)
    [...]

followed by

WARNING: Unknown HK2 failure detected:
MultiException stack 1 of 2
org.jboss.weld.exceptions.CreationException: WELD-001530: Cannot produce an instance of class com.acme.MyMessageBodyReader.
    at org.jboss.weld.injection.producer.NonProducibleInjectionTarget.produce(NonProducibleInjectionTarget.java:55)
    at org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider$CdiFactory$2.getInstance(CdiComponentProvider.java:242)
    at org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider$CdiFactory.provide(CdiComponentProvider.java:189)
    [...]
MultiException stack 2 of 2
java.lang.IllegalStateException: Unable to perform operation: create on org.glassfish.jersey.message.internal.MessageBodyFactory
    at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:389)
    at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:461)
    at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:114)
    [...]

I've found several examples of injecting Providers into a constructor, not the least in the subclasses of XmlRootElementJaxbProvider that ship with GlassFish 4.1 - after all, I want to reuse their class hierarchy anyway, as it's done in the linked thread.

Thanks in advance for any advice.


Answer:

I can't explain the root cause of the exception, but I ran into the same issue and at the time didn't feel like delving any more into the Jersey source than I already had.

I ended up lazily loading my custom MessageBodyReader/Writers so I could inject Providers into the wrapper. It's not pretty but it works.

Something along the lines of:

@Provider
@Consumes( "application/xml" )
public class MyLazyMessageBodyReader implements MessageBodyReader<Object> {
  @Context
  private Providers ps;

  private MessageBodyReader<Object> reader;

  @Override
  public final Object readFrom(
          Class<Object> type,
          Type type1,
          Annotation[] antns,
          MediaType mt,
          MultivaluedMap<String, String> mm,
          InputStream in)
          throws IOException, WebApplicationException
  {
    return this.getLazyReader().readFrom(type, type1, antns, mt, mm, in);
  }

  private MessageBodyReader<Object> getLazyReader() {
    if (this.reader == null) {
      this.reader = new MyMessageBodyReader(this.ps);
    }
    return this.reader;
  }
}

public class MyMessageBodyReader implements MessageBodyReader<Object> {
   public MyMessageBodyReader(Providers ps) {
      // try to do something with ps here
      // e.g. pass to a superclass constructor,
      // as required by the solution in the other thread
   }

   [...] // implemented interface methods
}

Question:

I have a jax-rs REST service, using JEE 7 (deployed in glassfish 4), which has a method to process HTTP POST on the resource:

    import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
    import org.glassfish.jersey.media.multipart.FormDataParam; 


    @POST
    @Path("/upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadVideo(
            @FormDataParam("files") InputStream uploadedInputStream,
            @FormDataParam("files") FormDataContentDisposition fileDetail) { 
        try {

            //do something

        } catch (Exception e) {

            e.printStackTrace();
        }

        return toReturn.build();
    }

My pom.xml in ejb is :

<dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>2.22.2</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>2.22.2</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-multipart</artifactId>
            <version>2.22.2</version>
        </dependency>

And I registered the rest resource with these annotations:

@ApplicationPath("/rest")
public class JaxRsActivator extends Application {

@Override
    public Set<Class<?>> getClasses() {
        final Set<Class<?>> resources = new HashSet<>();
        resources.add(MultiPartFeature.class);
        return resources;
    }

    @Override
    public Map<String, Object> getProperties() {
        Map<String, Object> properties = new HashMap<>();
        properties.put("jersey.config.server.provider.packages", "com.myBean.upload");
        return properties;
    }  
}

When I try to start the server I get this error:

java.lang.ClassCastException: Cannot cast org.glassfish.jersey.ext.cdi1x.transaction.internal.TransactionalExceptionInterceptorProvider to org.glassfish.jersey.server.spi.ComponentProvider

I already read this questions :Jersey 2 injection source for multipart formdata and How can I define a JAX-RS service that processes multi-part data in JEE? but I cannot find a solutions. Any suggestions?

-Log produced

WARN: WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds. WARN: WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds. WARN: WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds. WARN: WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds. WARN: WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds. WARN: WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.


Answer:

Finally I got the solution. For the first problem :

Cannot cast org.glassfish.jersey.ext.cdi1x.transaction.internal.TransactionalExceptionInterceptorProvider to org.glassfish.jersey.server.spi.ComponentProvider

the solution was the one given by @peeskillet.

My real problem was a little different since I miss to register all the packages with Rest Resource. I post here the solution for this problem anyway:

        @ApplicationPath("/rest")
        public class JaxRsActivator extends Application {

        @Override
            public Set<Class<?>> getClasses() {
                final Set<Class<?>> resources = new HashSet<Class<?>>();
                resources.add(MultiPartFeature.class);
                return resources;
            }

            @Override
            public Map<String, Object> getProperties() {
                Map<String, Object> properties = new HashMap<>();
                String array[] = {"com. myBean.home","com. myBean.upload","com.bandyer.search","com.bandyer.mail"};
                properties.put("jersey.config.server.provider.packages", array);
            }
        }

Question:

I'm writing a Java EE REST application (it runs under Glassfish 4.1) and I'm having problems reading a simple key-value JSON list. I'm trying to produce and consume a JSON using a POJO class, producing works fine, but consuming is not working. Let's get to the code. The POJO class I use for produce and consume JSON is like this:

public class Transport {
  protected Integer id;
  protected String name;
  protected Map<String, String> fields;
  // ...getters and setters...
}

The REST resource import those libraries (I've put here the relevant ones):

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;

The method who produces the JSON works fine, here it is:

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("test")
public Response testGet() {
  Transport sct = new Transport();
  sct.setId(1);
  sct.setName("test");
  HashMap<String, String> t1 = new HashMap();
  t1.put("aaa", "bbb");
  t1.put("bbb", "ccc");
  t1.put("ccc", "ddd");
  sct.setFields(t1);
  // createOkResponse is a class method that return Response type
  return createOkResponse(sct);
}

so I correctly obtain this output:

{
  "id": 1,
  "name": "test",
  "fields": {
     "aaa": "bbb",
     "ccc": "ddd",
     "bbb": "ccc"
  }
}

The method who consume the JSON, using the same POJO:

@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("test")
public Response testPut(Transport sct) {
  Map<String, String> fields = sct.getFields();
  // this code throws a NullPointerException at fields.entrySet() 
  // because fields is always null
  //for (Entry<String, String> field : fields.entrySet()) {
  //  LOG.log(Level.INFO, "*** field: {0} = {1}", new Object[]{field.getKey(), field.getValue()});
  //}
  return createOkResponse(sct);
}

Consuming the service with the same JSON above will result in an sct object with id and name properties set, but with fields property null, so the response of the method is:

{
  "id": 1,
  "name": "test",
  "fields": null
}

it's like the {"aaa": "bbb", "ccc": "ddd", "bbb": "ccc"} JSON object is being ignored. I've tried googling around but I don't understand what is wrong with my code, and I've seen no errors or warnings in the glassfish log. Any idea? Thanks.


Answer:

You can use an XmlAdapter, as mentioned in this post. The problem is the way that MOXy handles Maps. It uses JAXB under the hood, which was meant to be used for XML, and XML doesn't map very well to Maps (or key/value) pairs.

For this reason, instead of using MOXy for JSON (which is the default JSON provider in Glassfish), I would recommend using Jackson. Jackson should also be included in Glassfish 4.1. But you will need to disable MOXy, so the Jackson can register itself. To disable MOXy, just set the Jersey property jersey.config.server.disableMoxyJson to true.

Question:

Deserializing works fine if I just pass my custom object through

@POST
public Response saveCustomObject(CustomObject data)
{
    // Prints correct value
    System.out.println(data);
}

However, if it is a property on another object, it just gets the default value of my custom object

@POST
public Response saveCustomObjectWrapper(CustomObjectWrapper data)
{
    // Prints incorrect value
    System.out.println(data.getCustomObject());
}

My provider is registered and looks like this:

public CustomObject readFrom(Class<CustomObject> type, Type type1, Annotation[] antns, MediaType mt, MultivaluedMap<String, String> mm, InputStream in) throws IOException, WebApplicationException
{
    try {
        return new CustomObject(IOUtils.toString(in));
    } catch (Exception ex) {
        throw new ProcessingException("Error deserializing a CustomObject.", ex);
    }
}

Answer:

The problem is that the reader for all other objects doesn't do lookup/delegation while unmarshalling. What I mean by that, can be seen in this answer, where one reader looks up another reader based on the type. Assuming the format is JSON, whether you're using MOXy (the default with Glassfish) or Jackson, the result is the same. The reader is smart enough to handle the the JSON by itself, so doesn't need to lookup any other readers.

One solution would be to create another reader for the wrapper class, and do lookup/delegation, as seen in the link above. If you have a lot of these situations, you may can extend the default reader, and override its unmarshalling method, but I would completely advise against this, unless you really know what you're doing.

Another solution, depending on the serializer you're using, is to write JsonDeserializer (for Jackson) or XmlAdapter (for MOXy or Jackson). For Jackson an example would be something like (you can see a better example here)

public class CustomObjectDeserializer extends JsonDeserializer<CustomObject> { 

    @Override
    public CustomObject deserialize(JsonParser jp, DeserializationContext dc) 
            throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        return new CustomObject("Hello World");
    }
}

@JsonDeserialize(using = CustomObjectDeserializer.class)
public class CustomObject {
    public String message;
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
    public CustomObject(String message) { this.message = message; }
    public CustomObject(){}
}

In which case, there is no need for a custom reader at all. This will handle CustomObjects and objects that have CustomObject as a member. One problem with this is I'm not sure how or if you can get the InputStream. You just need to use the Jackson APIs to parse the JSON.

If you want to use Jackson instead of the default MOXy for glassfish, you can just add the Jackson dependency

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.13</version>
</dependency>

Then register the JacksonFeature, or simply disable MOXy, as mentioned here. If you want to continue using MOXy, I don't know if there is such thing as a class level adapter, so you will still need the reader as well as create a XmlAdapter for class members. It's a bit of a hassle, but that's why I recommend Jackson, for many other reasons, besides this particular use case. You can see an example of an adapter here

Now a lot of this answer is based on the assumption you are using JSON format, as you haven't specified the media type you are using. If it some other format, then I think maybe your only solution is to create another customer reader for the wrapper.

Question:

I'm trying to make a findAll on an Entity having 2 OneToMany relations. When I try the GET on the API, the server print an error 500, with no more indication. I think the problem comes from the JSON format, vecause when I try in XML, it works. These 2 cases seem to have the same problem, but the solutions don't work for me :

Glassfish JAX-RS JSON Mapping Simple Example Internal Server Error 500 No Logs Produced

JAXB on JAX-RS - JPA Entity with relations returns no JSON HTTP 500 no error on logs (Glassfish)

The Entity :

/**
 * Disruptive
 */
@Entity
@Table(name = "disruptive")
@XmlRootElement
public class Disruptive implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "disruptive_id_seq")
    @SequenceGenerator(name = "disruptive_id_seq", sequenceName = "disruptive_id_seq", allocationSize = 1)
    @Column(name = "id_disruptive")
    protected Integer idDisruptive;
    private String name;
    private String content;
    @ManyToOne
    @JoinColumn(name = "id_initial_situation", referencedColumnName = "id_initial_situation")
    protected InitialSituation initialSituation;
    @OneToMany(mappedBy = "disruptive") //,cascade = CascadeType.ALL,orphanRemoval = true
    protected List<Event> events;
    @OneToMany(mappedBy = "disruptive")
    protected List<FinalSituation> finalSituations;

    public Disruptive() {

    }

    public Disruptive(InitialSituation initialSituation) {
        this.setInitialSituation(initialSituation);
    }

    public Integer getIdDisruptive() {
        return idDisruptive;
    }

    public void setIdDisruptive(Integer idDisruptive) {
        this.idDisruptive = idDisruptive;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }    

    public InitialSituation getInitialSituation() {
        return initialSituation;
    }

    public void setInitialSituation(InitialSituation initialSituation) {
        this.initialSituation = initialSituation;
    }

    public List<FinalSituation> getFinalSituations() {
        return finalSituations;
    }

    public void setFinalSituations(List<FinalSituation> finalSituations) {
        this.finalSituations = finalSituations;
    }

    public List<Event> getEvents() {
        return events;
    }

    public void setEvents(List<Event> events) {
        this.events = events;
    }

    @Override
    public String toString(){
        return this.getName();
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 53 * hash + Objects.hashCode(this.idDisruptive);
        hash = 53 * hash + Objects.hashCode(this.name);
        hash = 53 * hash + Objects.hashCode(this.content);
        hash = 53 * hash + Objects.hashCode(this.initialSituation);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Disruptive other = (Disruptive) obj;
        if (!Objects.equals(this.name, other.name)) {
            return false;
        }
        if (!Objects.equals(this.content, other.content)) {
            return false;
        }
        if (!Objects.equals(this.idDisruptive, other.idDisruptive)) {
            return false;
        }
        if (!Objects.equals(this.initialSituation, other.initialSituation)) {
            return false;
        }
        return true;
    }
}

The WebService :

/**
 * DisruptiveFacadeREST
 */
@Stateless
@Path("disruptive")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public class DisruptiveFacadeREST extends AbstractFacade<Disruptive> {

    @PersistenceContext(unitName = "StoryGeneratorPU")
    private EntityManager em;

    public DisruptiveFacadeREST() {
        super(Disruptive.class);
    }

    @POST
    @Override
    public void create(Disruptive entity) {
        super.create(entity);
    }

    @PUT
    @Path("{id}")
    public void edit(@PathParam("id") Integer id, Disruptive entity) {
        super.edit(entity);
    }

    @DELETE
    @Path("{id}")
    public void remove(@PathParam("id") Integer id) {
        super.remove(super.find(id));
    }

    @GET
    @Path("{id}")
    public Disruptive find(@PathParam("id") Integer id) {
        return super.find(id);
    }

    @GET
    @Override
    public List<Disruptive> findAll() {
        return super.findAll();
    }

    @GET
    @Path("random")
    public Disruptive findRandom(@QueryParam("idInitialSituation") Integer idInitialSituation) {
        System.out.println(idInitialSituation);
        Query query;
        query = this.getEntityManager().createQuery("SELECT dis FROM Disruptive dis JOIN dis.initialSituation insi WHERE insi.idInitialSituation = :idInitialSituation");
        query.setParameter("idInitialSituation", idInitialSituation);
        List<Disruptive> list= query.getResultList();
        Disruptive dis = null;
        if (!list.isEmpty()){
            Collections.shuffle(list);
            dis = (Disruptive) list.get(0);
        }
        return dis;
    }

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }
}

I use a Glassfish Server and JAX-RS for the services.


Answer:

The issue is resolved (cfr comments under my question)

So I applied this solution : How can I get the stack trace when 500 server error happens in Jersey?

So I could see the stack trace :

GRAVE:   javax.ws.rs.WebApplicationException: HTTP 500 Internal Server Error
    at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.writeTo(MOXyJsonProvider.java:959)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:265)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:250)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
    at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:106)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
    at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:86)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1130)
    at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:711)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:444)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:434)
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:329)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1692)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:258)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:654)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:593)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:159)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:371)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:238)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:483)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:180)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573)
    at java.lang.Thread.run(Thread.java:748)
Caused by: javax.xml.bind.MarshalException
 - with linked exception:
[Exception [EclipseLink-25037] (Eclipse Persistence Services - 2.6.4.qualifier): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A cycle is detected in the object graph.  This will cause an infinite loop: Test -> be.isl.prj.story.entity.Event@1a1a69fc -> Test]
    at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:500)
    at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.writeTo(MOXyJsonProvider.java:957)
    ... 53 more
Caused by: Exception [EclipseLink-25037] (Eclipse Persistence Services - 2.6.4.qualifier): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A cycle is detected in the object graph.  This will cause an infinite loop: Test -> be.isl.prj.story.entity.Event@1a1a69fc -> Test
    at org.eclipse.persistence.exceptions.XMLMarshalException.objectCycleDetected(XMLMarshalException.java:415)
    at org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:212)
    at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
    at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
    at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.marshalSingleValue(XMLCompositeObjectMappingNodeValue.java:260)
    at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.marshal(XMLCompositeObjectMappingNodeValue.java:151)
    at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
    at org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
    at org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:443)
    at org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:243)
    at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
    at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
    at org.eclipse.persistence.internal.oxm.XMLCompositeCollectionMappingNodeValue.marshalSingleValue(XMLCompositeCollectionMappingNodeValue.java:334)
    at org.eclipse.persistence.internal.oxm.XMLCompositeCollectionMappingNodeValue.marshal(XMLCompositeCollectionMappingNodeValue.java:104)
    at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:149)
    at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
    at org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
    at org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:443)
    at org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:243)
    at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
    at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
    at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:766)
    at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLM
GRAVE:   arshaller.java:586)
    at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshalStreamOrWriter(XMLMarshaller.java:1126)
    at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:934)
    at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:877)
    at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:496)
    ... 54 more

And I resolved the problem putting the @XmlTransient that I forgot, in the getter of my OneToMany Relation (in Disruptive Entity).

Question:

I am developing RESTful web service using JAX-RS (Jersey) and Glassfish as server. I implemented simple method that returns list of entites and when I attempting to access it server drops 500 error with

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json.

I tried to add Genson lib to my project but this doesn't help. What's wrong with my code?

My entity

@XmlRootElement
public class Device {

    public Device(){}

    public Device(String vendor, String model) {
        this.vendor = vendor;
        this.model = model;
    }
    public String vendor;
    public String model;
}

Service

@Path("devices")
public class Devices {
    @Context
    Application app;
    @Context
    Providers providers;

    @GET
    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public Response getAll(){
        List<Device> result = new ArrayList<>();
        result.add(new Device("Samsung","Galaxy S4"));
        return Response.ok().entity(result).build();
    }
}

Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <display-name>Kontroller</display-name>
    <servlet>
        <servlet-name>Jersey REST Service</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.drozdov.kontroller.api, com.drozdov.kontroller.models</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey REST Service</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

</web-app>

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>com.drozdov</groupId>
    <artifactId>Kontroller</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.owlike</groupId>
            <artifactId>genson</artifactId>
            <version>0.99</version>
        </dependency>
    </dependencies>
</project>

Answer:

Are you using Jersey 2? If yes this is probably the reason why it does not work. Try with latest Genson release. It is supposed to also work out of the box with Jersey 2+.

<dependency>
  <groupId>com.owlike</groupId>
  <artifactId>genson</artifactId>
  <version>1.2</version>
</dependency>

Question:

I have an Angular application making a call cross origin. All of the GET calls work great. The DELETE calls, however throw the error:

XMLHttpRequest cannot load http://my.url.com:8080/api/invoices/12768. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. 

On the backend I am using JAX-RS with Glassfish 4.1 and Java 8. I am creating the ResponseBuilder like so:

ResponseBuilder responseBuilder = Response
                    .status(status)
                    .type(MediaType.APPLICATION_JSON)
                    .header("Access-Control-Allow-Origin", "*")
                    .header("Access-Control-Allow-Credentials", "true")
                    .header("Access-Control-Allow-Methods", "POST, GET, DELETE")
                    .header("Access-Control-Max-Age", "1209600")
                    .allow("OPTIONS");

In Angular I am making the service call like so:

$http.delete(requestUrl)
                     .success(function (data, status, headers, config) {
                    deferred.resolve(data);
                }).error(function (data, status, headers, config) {
                    deferred.reject(status);
                });

The thing is, this works perfectly well:

$http.get(requestUrl)
                     .success(function (data, status, headers, config) {
                    deferred.resolve(data);
                }).error(function (data, status, headers, config) {
                    deferred.reject(status);
                });

Any idea why GET's would be working, but not DELETE?

Edit:

As another note, I know it isn't the server side, because if I run the delete call through Advanced Rest Client on my local computer the DELETE works perfectly.

Edit 2:

Request headers

User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/{ipaddress} Safari/537.36
Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
Content-Type: application/json 
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,es;q=0.6
Cookie: treeForm_tree-hi=treeForm:tree:applications

Response headers

Server: GlassFish Server Open Source Edition 4.1 
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1 Java/Oracle Corporation/1.8)
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, DELETE
Access-Control-Max-Age: 1209600
Allow: OPTIONS 
Content-Type: application/json 
Date: Fri, 07 Nov 2014 23:39:10 GMT 

Content-Length: 0

These are the headers from the working Advanced Rest Client


Answer:

Ok, so apparently Angular strips content-type from the header. Using this works:

$http.delete({url:request,headers:{'Content-Type':'application/json'}})

Question:

I'd like to get JAXRS to push all json details for a specific class property into a JsonObject object.

Let's say I have the following class:

public class MyMessage implements Serializable {

    private PayloadType payloadType;    

    private JsonObject payload;
}

REST method of:

@POST
@Path("/send")
@Consumes(MediaType.APPLICATION_JSON)
public Response send(MyMessage message) 

I'd like to POST the following JSON, but have the payload property set as a javax.json.JsonObject object.

{
   payloadType:'MESSAGE',
   payload:{
      subject:"My Subject",
      body:"This is a message"
   }
}

I'm running on Glassfish, so I was expecting that message reader for JsonObject were included with org.glassfish.jersey.media, which is support to be included in the GF4.1. Add the following maven dependency just causes ambiguous class exceptions.

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-processing</artifactId>
    <version>2.22.1</version>
</dependency>

Answer:

So there are a couple things stopping you here.

  1. javax.json (or JSONP) does not handle POJOs. It only handles the javax.json API. If you what you are expecting is that the original provider handle the POJO, while the JSONP provider handle the javax.json, it doesn't work like that. Either you will use the one that handles the POJOs (which doesn't know javax.json or you use the one that handles javax.json. (We do make this happen below though :-)

  2. Glassfish's default provider is MOXy. So we need to disable to to use any other provider. To disable MOXy, you need to set this property

    ServerProperties.MOXY_JSON_FEATURE_DISABLE

    to true. Either in your web.xml or your Java config.

So to make this work, we should make sure that we are using Jackson. Jackson has the jackson-datatype-jsr353 module which allows to do exactly what you are trying to do, javax.json in POJO.

Glassfish has the Jackson provider already, but you should add it anyway in a provided scope. So add these two dependencies

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.10.4</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr353</artifactId>
    <version>2.3.3</version>
</dependency>

If yoo pay attention to the versions, I am using the same versions that are included in Glassfish 4.1. It uses Jersey 2.10.4 and Jackson 2.3.3. You want the versions to conflict. Even though the jersey-media-json-jackson is provided, it's still a good idea to try and use the same version as the server, when compiling.

Also you should register the JacksonFeature with your application.

And the last thing we need is to register the JSR353Module so that we can get the javax.json support with Jackson. To do that just register the following provider with your application.

@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {

    private final ObjectMapper mapper;

    public ObjectMapperProvider() {
        mapper = new ObjectMapper();
        mapper.registerModule(new JSR353Module());
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }
}

That's it. I've tested it, and it should work.

Question:

I am having trouble attaching a ContainerRequstFilter to a very simple JAX-RS rest application inside Glassfish4.

I believe that I've followed the instructions from both the javadoc and various other tutorial sources, but I am now at a complete loss.

The entire source (very short) is below, with the expected functionality:

The second bit is meant the be implemented as a filter. What actually happens is that the first bit (login) works, and the second bit (verify) completely ignores the filter (including nothing in the logs to indicate that the filter ran). That is, the output is just "Every thing is fine, uname", rather than a 401 error.

What I want to understand is the way to get the filter attached to the verify action. For reference

  • I'm running glassfish 4.1 build 13
  • I'm compiling and deploying using gradle, with the deployment action
    • assassin deploy --force --contextroot /app /path/to/app.war
  • Glassfish reports that it's using Jersey 2.10.4

Here is the entirety of the source related to the application:

RestApp.java

package test.pack;

import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/api")
public class RestApp extends Application
{
    @Override
    public Set<Class<?>> getClasses()
    {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        classes.add(Login.class);
        return classes;
    }
}

Login.java

package test.pack;

import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

@Stateless
@Path("login/")
@Produces("text/json")
public class Login
{
    @GET
    @Path("{username}/{password}")
    public Response login(@PathParam("username") String username, @PathParam("password") String password)
    {
        System.out.println("Logging in");
        return Response.ok("You are logged in, " + username).build();
    }

    @GET
    @Path("/verify/{username}")
    @Secured
    public Response verify(@PathParam("username") String username)
    {
        System.out.println("Verify");
        return Response.ok("Everything is fine, " + username).build();
    }

Secured.java

package test.pack;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.ws.rs.NameBinding;

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Secured 
{
}

LoggedInFilter.java

package test.pack;

import java.io.IOException;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Response;

@Secured
public class LoggedInFilter implements ContainerRequestFilter
{
    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException 
    {
        System.out.println("request");
        requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
    }
}

Answer:

Ugh. That's embarrassing.

The next tutorial I visited had the solution, which was to register the filter in the RestApp class.

RestApp.java

@ApplicationPath("/api")
public class RestApp extends Application
{
    @Override
    public Set<Class<?>> getClasses()
    {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        classes.add(Login.class);
        return classes;
    }

    @Override
    public Set<Object> getSingletons()
    {
        Set<Object> singletons = new HashSet<Object>();
        singletons.add(new LoggedInFilter());
        return singletons;
    }
}

I'll leave the answer here rather than deleting the question, since it was only in one of 4 tutorials that I read, and so this might be at least a little interesting.

Question:

I am curious to know which json marshalling/unmarshalling framework is used by Glassfish/Payara is case of JAX-RS and how I can add custom json mapper class into it.

I would like to write a custom serializer for my Enum class. I use provided scope in my pom.xml for jaxrs javaee-api 7.0 so default Glassfish libraries are used.

I tried to use @JsonValue and wrote a class wich implements javax.ws.rs.ext.MessageBodyWriter and JsonSerializer<T> as well. Do not work either as I expect.

This is my enum class:

public enum ErrorCode {
    MY_ERROR(123456);

    private int value;

    ErrorCode(final int value) {
        this.value = value;
    }

    @JsonValue
    public int  getValue() {
        return value;
    }
}

The class which uses enum:

public class ErrorInfo {
    private ErrorCode errorCode;

    public String toJson() {
        try {
            return new ObjectMapper().writer().withDefaultPrettyPrinter().writeValueAsString(this);
        } catch (JsonProcessingException e) {
            // TODO: do something here...
        }
    }
}

And the JAX-RS class where I would like to send back the ErrorInfo instance as a json:

@Provider
public class MyExceptionMapper implements ExceptionMapper<Throwable> {
    @Override
    public Response toResponse(Throwable throwable) {
        ...
        return Response
                .status(errorInfo.getHttpStatus())
                .type(ExtendedMediaType.APPLICATION_JSON_UTF8)
                .entity(errorInfo)
                .build();
    }
}

If I use the code above then the errorCode value is "MY_ERROR" string instead of the int 123456 value.

If I use my extra errorInfo.toJson() method then @JsonValue annotation does the magic but I would like to avoid writing extra code to handle enum serialization issue.

What is the proper way to configure / add extra enum mapper class to the default JAX-RS json library in Glassfish/Payara?


Answer:

By default, Payara Server uses MOXy to map to/from JSON. You can use an alternative like Jackson, if you add Jackson to your app and add JacksonFeature into JAX-RS classes: Force Glassfish4 to use Jackson instead of Moxy

In the upcoming Payara 5, which will support Java EE 8, JSON marshalling will be handled in a standard way prescribed by the JSON-Binding

Question:

I'm using Glassfish 4.1.2

I have a jax-rs endpoint that I want to return a JSON object serialised from my POJO entity.

The POJO:

@XmlRootElement
public class MyObj {

    public MyObj() {}

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

}

The resource:

@Path("/something")
public class MyResource {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public MyObj getMyObject() {
        MyObj myObj = new MyObj();
        myObj.setValue("Some Value");
        return myObj;
    }

}

Produces two exceptions, The first is thrown when the resource is first accessed after the server is started:

javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoClassDefFoundError: javax/xml/parsers/ParserConfigurationException

All subsequent requests produce the exception:

javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoClassDefFoundError: Could not initialize class org.eclipse.persistence.jaxb.BeanValidationHelper

However, if I get the result as an XML (i.e. I change to @Produces(MediaType.APPLICATION_XML)) it works without exception and the xml is returned no problems.

My request headers accept both xml and json.

UPDATE

My project's dependencies are:

javax:javaee-api:7.0
com.lambdaworks:scrypt:1.4.0
commons-codec:commons-codec:1.10
org.apache.commons:commons-lang3:3.6

I've basically stripped this project down to its bare bones.

UPDATE 2

Following advice from @peeskillet by adding jersey.config.server.disableMoxyJson, true to the Application properties map does kind of work:

@ApplicationPath("")
public class MyServer extends Application {

    @Override
    public Map<String, Object> getProperties() {
        Map<String, Object> map = new HashMap<>();
        map.put("jersey.config.server.disableMoxyJson", true);
        return map;
    }

}

The initial request fails with:

javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoClassDefFoundError: com/fasterxml/jackson/module/jaxb/JaxbAnnotationIntrospector

BUT then all subsequent requests do work and I can get the JSON in the respose.

I am a little concerned though that it initially fails.


Answer:

I couldn't get this working correctly with Glassfish 4.1.2, I switched to using WildFly 10.1.0.Final and it worked right away.

UPDATE

Coming back to this I managed to get Glassfish working with Jackson.

It seems that java.lang.NoClassDefFoundError: com/fasterxml/jackson/module/jaxb/JaxbAnnotationIntrospector is because Glassfish 4.1.2 doesn't come bundled with a jackson-module-jaxb-annotations.jar.

The solution is to add the jackson-module-jaxb-annotations.jar to <glassfish install>/glasfish4/glassfish/modules

Then disable Moxy using:

@ApplicationPath("")

public class MyServer extends Application {

    @Override
    public Map<String, Object> getProperties() {
        Map<String, Object> map = new HashMap<>();
        map.put("jersey.config.server.disableMoxyJson", true);
        return map;
    }

}