users@jersey.java.net

Re: [Jersey] Here is what I want to do (TDD testing with Spring)

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 24 Mar 2009 12:27:06 +0100

Hi Matt,

The problem is in your BarResourceRestTest class you are not
configuring Jersey to use Spring.

The following does not set up the Jersey Spring configuration:

      threadSelector = GrizzlyWebContainerFactory.create(baseUri,
initParams);

You might be able to do this:

      threadSelector = GrizzlyWebContainerFactory.create(
           
com.sun.jersey.spi.spring.container.servlet.SpringServlet.class,
          baseUri,
          initParams);

But i really do not know how the Jersey configuration will get access
to the application context you have declared via the annotation. It
might be necessary to extend the Jersey SpringServlet in such a case.
The SpringServlet.initiate method is as follows:

     @Override
     protected void initiate(ResourceConfig rc, WebApplication wa) {
         try {
             final WebApplicationContext springWebContext =
WebApplicationContextUtils.
                      
getRequiredWebApplicationContext(getServletContext());
             final ConfigurableApplicationContext springContext =
                     (ConfigurableApplicationContext)springWebContext;

             wa.initiate(rc, new SpringComponentProviderFactory(rc,
springContext));
         } catch( RuntimeException e ) {
             LOGGER.log(Level.SEVERE, "Exception occurred when
intialization", e);
             throw e;
         }
     }

The jersey-spring module uses Grizzly for unit tests. See the
following class for the setup:

   https://jersey.dev.java.net/source/browse/*checkout*/jersey/trunk/jersey/contribs/spring/src/test/java/com/sun/jersey/spring/AbstractResourceTest.java


Note that with Spring integration it is not necessary to explicitly
register resource and provider classes if those classes are also
Spring registered. See here for more details:

   https://jersey.dev.java.net/source/browse/*checkout*/jersey/tags/jersey-1.0.2/api/contribs/jersey-spring/index.html

Paul.


On Mar 24, 2009, at 11:58 AM, Mats Henricson wrote:

> OK, here is what I want to do as a TDD developer. Sorry for
> such a long email. I've tried to simplify my code as much as
> possible for this post, and may have missed in cases.
>
> First lets assume I have a class used inside a Jersey resource
> for its implementation:
>
> package foo;
>
> @Component
> public class BarImpl implements Bar {
> public String getHello(long id) throws BarException {
>
> if (id == -1) {
> throw new BarException("No such user: " + id);
> }
>
> return "Hello " + id;
> }
> }
>
> That BarException is in package foo.exceptions and totally trivial.
> The Bar interface is also totally trivial.
>
> Now this is my resource class:
>
> package foo.resource;
>
> @Path("/hello")
> @Component
> public class BarResource {
>
> @Autowired
> private Bar bar;
>
> @GET
> @Produces("text/plain")
> public String getHello(@QueryParam("id") long id) throws
> BarException {
> return bar.getHello(id);
> }
>
> public void setBar(Bar bar) {
> this.bar = bar;
> }
> }
>
> Now, lets test this baby with JUnit. I write an applicationContext-
> test.xml:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <beans LOTS OF XML MUMBO JUMBO>
>
> <bean id="bar" class="foo.BarImpl">
> </bean>
>
> <bean id="barResource" class="foo.resource.BarResource">
> <property name="bar" ref="bar"/>
> </bean>
> </beans>
>
> The JUnit test of the resource class is a beauty of simplicity:
>
> @RunWith(SpringJUnit4ClassRunner.class)
> @ContextConfiguration(locations = { "/applicationContext-test.xml" })
> public class BarResourceTest {
>
> @Autowired
> private BarResource barResource;
>
> @Test
> public void testWithBogusId() {
> try {
> /* IGNORE RETURNED VALUE */ barResource.getHello(-1);
> Assert.fail();
> }
> catch (BarException e) {
> String message = e.getMessage();
> Assert.assertEquals(message, "No such user: -1");
> }
> }
>
> @Test
> public void testWithOkId() throws BarException {
> String message = barResource.getHello(77);
> Assert.assertEquals(message, "Hello 77");
> }
> }
>
> Now, how do I test this resource over HTTP? A complicating issue is
> that
> I have an exception mapper:
>
> @Provider
> public class BarExceptionMapper implements
> ExceptionMapper<BarException> {
>
> public Response toResponse(BarException e) {
> return Response.status(Response.Status.NOT_FOUND).
> entity(e.toString()).type("text/plain").build();
> }
> }
>
> My (probably totally naive) attempt was this, from looking all over
> the
> net for examples:
>
> @RunWith(SpringJUnit4ClassRunner.class)
> @ContextConfiguration(locations = { "/applicationContext-test.xml" })
> public class BarResourceRestTest {
>
> private static final String baseUri = "http://localhost:9998/";
> private static final String resourcePackage =
>
> BarResource.class.getPackage().getName();
> private static final String exceptionMapperPackage =
>
> BarExceptionMapper.class.getPackage().getName();
>
> private SelectorThread threadSelector;
>
> @Before
> public void setup() throws IllegalArgumentException, IOException {
> final Map<String, String> initParams = new HashMap<String,
> String>();
>
> initParams.put("com.sun.jersey.config.property.packages",
> resourcePackage + ";" + exceptionMapperPackage);
>
> initParams.put("com.sun.jersey.config.property.resourceConfigClass",
>
> "com.sun.jersey.api.core.PackagesResourceConfig");
>
> threadSelector = GrizzlyWebContainerFactory.create(baseUri,
> initParams);
> }
>
> @After
> public void shutDown() {
> threadSelector.stopEndpoint();
> }
>
> @Test
> public void testWithBogusId() throws IOException {
> URL url = new URL(baseUri + "hello/-1");
> String data = getDataFromUrl(url);
>
> Assert.assertTrue(data.equals("No such user: -1"));
> }
>
> @Test
> public void testWithOkId() throws IOException {
> URL url = new URL(baseUri + "hello/77");
> String data = getDataFromUrl(url);
>
> Assert.assertTrue(data.equals("Hello 77"));
> }
>
> private String getDataFromUrl(URL url) throws IOException {
> // Read all the text returned by the server
> BufferedReader in = new BufferedReader(
> new
> InputStreamReader(url.openStream()));
> StringBuffer data = new StringBuffer(1000);
> String line;
>
> while ((line = in.readLine()) != null) {
> data.append(line);
> }
>
> in.close();
>
> return data.toString();
> }
> }
>
> I can't get this to work. I've fiddled with various things, and I
> either
> get a NullPointer where the bar object is used in this function:
>
> public String getHello(@QueryParam("id") long id) throws
> BarException {
> return bar.getHello(id);
> }
>
> Or, I get an exception, because the ExceptionMapper isn't in place.
>
> I clearly don't want to fiddle with web.xml. I just want to deploy my
> resource in Grizzly (or whatever standalone container) and make an
> HTTP
> call. I would also prefer not to embed GlassFish in my JUnit tests.
> We use WebLogic, but not in our JUnit tests, of course.
>
> Mats
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>