Accueil > Apache CXF, Mongo JEE, MongoDB > Mongo JEE [step5]

Mongo JEE [step5]


In [step4] we have tranformed our LogsServlet to a JAX-RS LogsService which uses JAX-RS StreamingOutput. At this step the service returns JAX-RS Response :

@Path("/logs")
public class LogsService {

  @Path("/all")
  public Response findAll() {
    ...
  }
}

It’s very difficult to use this service in other context than JAX-RS (like using the service in fat client, using the service in a JUnit etc). Imagine you wish to write some JUnits which tests that our LogsService service returns some logs. With our current logs service, it’s hard to write that :

@Test
public void testNotEmptyLogs() {
  LogsService service = new LogsService();
  Response jaxrsResponse = service.findAll();
  // How to get the list of logs to test that logs are not empty?
}

When you develop a service, the best mean is that you don’t link it to a framework. For instance :

  • if your service returns list of Pojo :
    @Path("/logs")
    public class LogsService {
    
      @Path("/all")
      public List<Log> findAll() {
        ...
      }
    }
    

    you can write this test :

    @Test
    public void testNotEmptyLogs() {
      LogsService service = new LogsService();
      List<Pojo> pojoList = service.findAll();
      Assert.assertFalse(pojoList.isEmpty());
    }
    
  • if your service returns a Mongo DBCursor :
    @Path("/logs")
    public class LogsService {
    
      @Path("/all")
      public DBCursor findAll() {
        ...
      }
    }
    

    you can write this test :

    @Test
    public void testNotEmptyLogs() {
      LogsService service = new LogsService();
      DBCursor cursor= service.findAll();
      Assert.assertFalse(cursor.toArray().isEmpty());
    }
    

With JAX-RS you can write services which returns anything (List of Pojo, Mongo DBCursor), but it’s not magic and you need JAX-RS provider to serialize (in our case) List of Pojo, DBCursor etc into JSON stream :

  • in this article we will see how to manage JAX-RS service with Pojo. We will use MongoJack to get list of Log Pojo from Mongo DB and the Apache CXF JSONProvider, the JAX-RS provider to serialize Pojo to a JSON stream.
  • in the next article [step6] we will see how to manage JAX-RS service with Mongo DBCursor by using the Mongo JEE JAX-RS providers.

Download

You can download step5.zip which hosts the Eclipse Project which contains the explained sources in this article. To use it, unzip it and import this project in your Eclipse workspace. As soon as you will do that, your workspace will look like this :

This Eclipse project contains:

  • LogService is JAX-RS service which returns list of Pojo by using MongoJack.
  • MyJaxrsApplication is JAX-RS application which register the JAX-RS LogsService.
  • web.xml declares the Apache CXF JAX-RS implementation and set MyJaxrsApplication as JAX-RS Application

Download JARs with maven

This project contains the same dependencies than step4, and additional dependencies :

  • in our case we need org.apache.cxf.jaxrs.provider.json.JSONProvider, the JAX-RS provider of Apache CXF used to serialize/deserialize Pojo (which are annotated with JAXB annotations) to JSON stream :
    <dependency>
    	<groupId>org.apache.cxf</groupId>
    	<artifactId>cxf-rt-rs-extension-providers</artifactId>
    	<version>2.7.4</version>
    </dependency>
    
  • JSONProvider of Apache CXF uses jettison to manage JSON read/write :
    <dependency>
    	<groupId>org.codehaus.jettison</groupId>
    	<artifactId>jettison</artifactId>
    	<version>1.3.3</version>
    </dependency>
    
  • Pojo Mapper MongoJack is used to get Pojo from Mongo DB like we have explained in the step1:
    <dependency>
    	<groupId>org.mongojack</groupId>
    	<artifactId>mongojack</artifactId>
    	<version>2.0.0-RC5</version>
    </dependency>
    • What is JAX-RS provider?

      I suggest you to read What does Provider in JAX-RS mean? In our case we will need Entity Providers

      These providers control the mapping of data representations (like XML, JSON, CSV) to their Java object equivalents.

      We will use Apache CXF org.apache.cxf.jaxrs.provider.json.JSONProvider which uses jettison.

      Pojo Log

      Create a Pojo Log like we have explained in the [step1] and add the JAXB @XmlRootElement annotation :

      package org.samples.mongodb.services;
      
      import java.util.Date;
      
      import javax.persistence.Id;
      import javax.xml.bind.annotation.XmlRootElement;
      
      @XmlRootElement
      public class Log {
      
      	@Id
      	private String id;
      
      	private String url;
      	private Date created;
      
      	public String getId() {
      		return id;
      	}
      
      	public void setId(String id) {
      		this.id = id;
      	}
      
      	public String getUrl() {
      		return url;
      	}
      
      	public void setUrl(String url) {
      		this.url = url;
      	}
      
      	public Date getCreated() {
      		return created;
      	}
      
      	public void setCreated(Date created) {
      		this.created = created;
      	}
      
      }
      

      LogsService

      Create the org.samples.mongodb.services.LogsService which uses MongoJack and returns list of Pojo Log like this :

      package org.samples.mongodb.services;
      
      import java.util.List;
      
      import javax.ws.rs.Consumes;
      import javax.ws.rs.GET;
      import javax.ws.rs.Path;
      import javax.ws.rs.Produces;
      import javax.ws.rs.core.MediaType;
      
      import org.mongojack.JacksonDBCollection;
      
      import com.mongodb.DB;
      import com.mongodb.DBCollection;
      import com.mongodb.jee.MongoHolder;
      
      @Path("/logs")
      public class LogsService {
      
      	@GET
      	@Path("/all")
      	@Produces(MediaType.APPLICATION_JSON)
      	public List<Log> findAll() {
      
      		DB db = MongoHolder.connect().getDB("websites");
      		DBCollection dbColl = db.getCollection("logs");
      
      		JacksonDBCollection<Log, String> coll = JacksonDBCollection.wrap(
      				dbColl, Log.class, String.class);
      		return coll.find().toArray();
      	}
      
      }
      

      Test LogsService

      • run the StartServer class to start the server.
      • access with your webbrowser to the URL http://localhost:8081/mongo/jaxrs/logs/all/ to see the JSON array of logs and see the « application/json » of the content type :

      You can check that the JSON array is not the same than the Mongo JSON array like (see [step4]) :

      {"log":
        [{"created":"2013-05-10T16:17:37.515+02:00",
          "id":"518d01813bfe01bef797d031",
          "url":"http:\/\/www.mongodb.org\/"}
        ...
        ]
      }
      

      JSONProvider Troubleshooting

      When I have tried to develop this article, I have spent a long time to use correctly JSONProvider. I had every time the error :

      No message body writer has been found for response class ArrayList.

      Here the 3 rules to respect, when your service returns a List of Pojo, to avoid this error :

      1. check org.apache.cxf.jaxrs.provider.json.JSONProvideris in the classpath. Since 2.6.x, this JAX-RS provider is hosted in the cxf-rt-rs-extension-providers*.jar.
      2. check that Jettison*.jar is in the classpath. JSONProvider uses Jettison to read/write JSON.
      3. check that your Pojo is annotated with JAXB @XmlRootElement annotation.

      Conclusion

      In this article we have modified our LogsService to return a List of Pojo getted from the Mongo DB with MongoJack. Apache CXF JSONProvider is used in this case to serialize list of Pojo to a JSON array. Using Pojo witth Mongo and JAX-RS works great but :

      • you need to create a Pojo.
      • you need to annotate the Pojo with JAXB annotation.
      • you need to serialize the Pojo to a JSON stream.

      Mongo stores their data with BSON representation (looks like JSON), so .., why we could not to use this stream instead of creating a Pojo? In the next article [step6], we will modify our LogsService to use Mongo DBCuror instead of List of Pojo.

Catégories :Apache CXF, Mongo JEE, MongoDB
  1. Aucun commentaire pour l’instant.
  1. Mai 14, 2013 à 10:45
  2. Mai 15, 2013 à 9:42

Laisser un commentaire