5

I wrote an maven application which should run on Glassfish 4.

The Standard ApplicationConfig looks like this:

@javax.ws.rs.ApplicationPath("resources")
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:

        try {
           Class jsonProvider = Class.forName("org.glassfish.jersey.jackson.JacksonFeature");

        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(getClass().getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        addRestResourceClasses(resources);
        return resources;
    }

The problem now is, that my resources which generate Json should use jackson 2.3 annotations. But my glassfish uses some codehaus. ... packages to provide json. codehaus is the old version of jackson. I want to use the new one from fasterxml which provides the @JsonIdentityInfo annotation.

I thought that i could solve my problem by writing:

@javax.ws.rs.ApplicationPath("resources")
public class ApplicationConfig extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new java.util.HashSet<Class<?>>();

        resources.add(JacksonFeatures.class);  //from the com.fasterxml.jackson.jaxrs.annotation Package
        resources.add(JacksonJaxbJsonProvider.class);
        resources.add(JacksonJsonProvider.class);

        addRestResourceClasses(resources);
        return resources;
    }

But no effect. Now Glassfish uses the standard JsonProvider Moxy... which i dont want to use. Do you have any tips how i can force glassfish to use my library instead of the buildin-libraries? Or can i change the buildin library to the newer one?


And if you know how to solve this. could you please provide a little code-snippet?


EDIT 1:


After trying the first approach to solve it:

new ApplicationConfig:

@javax.ws.rs.ApplicationPath("resources")
public class ApplicationConfig extends ResourceConfig {

    public ApplicationConfig() {
        //register( new GZipEncoder() );
        register( JacksonFeature.class );
    }

    private void addMyResources() {
        //a lot of resources.
    }

}

JacksonFeature:

public class JacksonFeature implements Feature {

        public boolean configure( final FeatureContext context ) {

            String postfix = '.' + context.getConfiguration().getRuntimeType().name().toLowerCase();

            context.property( CommonProperties.MOXY_JSON_FEATURE_DISABLE + postfix, true );

            context.register( JsonParseExceptionMapper.class );
            context.register( JsonMappingExceptionMapper.class );
            context.register( JacksonJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class );

            return true;
        }
    }

pom:

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-base</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-common</artifactId>
        <version>2.4</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-server</artifactId>
        <version>2.4</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpcore</artifactId>
        <version>4.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.3</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>2.5.0</version>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
    </dependency>
</dependencies>

Dependencies:

https://i.stack.imgur.com/uA4V2.png

Error:

SEVERE:   Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [Ref<ContainerRequest>] with qualifiers [@Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject org.glassfish.jersey.server.internal.routing.UriRoutingContext(Ref<ContainerRequest>, ProcessingProviders)]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Ref<ContainerRequest>] with qualifiers [@Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject org.glassfish.jersey.server.internal.routing.UriRoutingContext(Ref<ContainerRequest>, ProcessingProviders)]
    at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:403)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:325)
    at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:177)
    ...

or

SEVERE:   Exception while loading the app
SEVERE:   Undeployment failed for context /blueserver
INFO:   file:/C:/bluetrail/blueserver/target/blueserver-0.0.0.1/WEB-INF/classes/_de.bluetrail_blueserver_war_0.0.0.1PU logout successful
SEVERE:   Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [IterableProvider<InjectionResolver<Object>>] with qualifiers [@Default] at injection point [[BackedAnnotatedParameter] Parameter 2 of [BackedAnnotatedConstructor] @Inject org.glassfish.jersey.internal.inject.JerseyClassAnalyzer(@Named ClassAnalyzer, IterableProvider<InjectionResolver<Object>>)]

EDIT 2:

i will now post some classes of my project. In that classes i included all Annotations that i use.

i have like 16 entities like that:

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;

@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.None.class, property = "id", scope=Address.class)
//the JsonIdentityInfo is the reason i need Jackson 2
public class Address implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String postalCode;
    private String city;
    private String country;
    private String street;
    private String houseNumber;
    @Embedded
    private Coordinate coordinate;
    //getters, setters , etc.
}

then i have a lot of DAO's like that:

import de.ibs.trail.entity.Address;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;

@Stateless
public class AddressDao extends GenericDao {
    public Address getAddress(long id){
        return em.find(Address.class, id);
    }

    public List<Address> getAddresses(){
        List<Address> address = em.createQuery("SELECT a FROM Address a", Address.class).getResultList();
        return address;
    }
}

and finally i have a lot of REssources like that:

import de.bluetrail.blueserver.dao.AddressDao;
import de.ibs.trail.entity.Address;
import java.util.List;
import javax.ejb.Stateless;
import javax.inject.Inject;
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.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;

@Path("dummy")
@Stateless
public class DummyResource {

    @Context
    private UriInfo context;
    @Inject userAuth user;
    @Inject addressDao AddressDao;

    public DummyResource() {
    }

    @GET
    @Produces("application/json")
    public List<Address> getAddress() {
        return AddressDao.getAddresses();
    }

}

Thats the first part. As a second part i have a class for some Google Services. Because i want to try to use some Google GeoLocation and Routing. I put the Google-Code into a pasteBin file, because its so huge:

http://pastebin.com/u3e0dms6

there i use libraries like:

import com.fasterxml.jackson.databind.ObjectMapper;
import de.ibs.trail.entity.Address;
//some other entities
//...
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Set;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;

I hope that helps. All the other classes use the same annotations.

Laokoon
  • 1,241
  • 4
  • 24
  • 47
  • i added "jackson.jaxrs.base" to my dependencies, now i get another weld error. WELD-001408 Unsatisfied dependencies for type [IterableProvider>] – Laokoon Dec 22 '13 at 11:22

1 Answers1

11

First make sure you have the following in your pom.xml:

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

Then make sure you DO NOT have this in any pom.xml:

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

Then you need to disable moxy. The easiest way to do this is to ditch your Application class and replace is with a ResourceConfig class. First lets create YOUR JacksonFeature class:

    public class JacksonFeature implements Feature {

        public boolean configure( final FeatureContext context ) {

            String postfix = '.' + context.getConfiguration().getRuntimeType().name().toLowerCase();

            context.property( CommonProperties.MOXY_JSON_FEATURE_DISABLE + postfix, true );

            context.register( JsonParseExceptionMapper.class );
            context.register( JsonMappingExceptionMapper.class );
            context.register( JacksonJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class );

            return true;
        }
    }

Two interesting things here, first I disabled moxy and second I made sure to add the JacksonException mappers. This way you will get better errors than internal server error if there is a parsing or generation exception. Okay, last step it so rewrite your Application as a ResourceConfig class:

@javax.ws.rs.ApplicationPath("resources")
public class RestApplication extends ResourceConfig {

    public RestApplication() {
        register( new GZipEncoder() );
        register( JacksonFeature.class );
    }

    private void addMyResources() {
        register( MyResource1.class );
        register( MyResource2.class );
    }
}

That should do it. Also, instead of registering the resources one by one like this, if you know their path you can just remove all that code and add this to the constructor of RestApplication:

package( "com.me.myrestresourcespackage" );

Hope this helps.

robert_difalco
  • 4,821
  • 4
  • 36
  • 58
  • HI, i read this kind of solution already on the web. i think it was also from you ;-). So i will try it again. You can read the result of my second try in my original post above. When i try your solution I get some problems with some dependencies. Do you know how i can solve this? I read that it could be because of guava. – Laokoon Dec 21 '13 at 21:16
  • 2
    You'll have to add your code that has the annotations so we can see it. – robert_difalco Dec 21 '13 at 22:50
  • thanks for your time. i hope that we can solve that :-) – Laokoon Dec 22 '13 at 11:16
  • Okay, this is now a CDI and HK2 question, not so much a Jackson and Jersey question. Check out this question and answer. http://stackoverflow.com/questions/17224270/how-to-enable-cdi-inject-in-web-service-jaxrs-jersey-on-java-se-running-grizzl – robert_difalco Dec 23 '13 at 17:25
  • 2
    JsonParseExceptionMapper is declared as deprecated :( – Dejell Feb 11 '14 at 19:27
  • The same is valid to do not use `com.sun.jerseyjersey-json1.8`? – Filipe Apr 11 '14 at 21:47
  • This still not working, any another configuration is needed to provide a restful service?! – Filipe Apr 12 '14 at 00:36
  • If you are using the web.xml approach, another way to disable MOXy is setting the init param `jersey.config.disableMoxyJson.server` to `true` in the Jersey servlet. – A. Rodas Jun 28 '14 at 18:27
  • For Jersey 2.27 you can still use `jersey-media-json-jackson` artifact but change `context.property(CommonProperties.MOXY_JSON_FEATURE_DISABLE_SERVER, true)` on JacksonFeature – Diego de la Riva Dec 15 '18 at 14:05