On May 31, 2010, at 10:40 PM, Bartosz Bobnis wrote:
> Hello,
>
> > What version of Grizzly are you using? perhaps there is an issue in
> > Grizzly when shutting down?
>
> <properties>
> <jerseyVersion>1.3-SNAPSHOT</jerseyVersion>
> <!--jerseyVersion>1.1.5.1</jerseyVersion-->
> </properties>
> <dependency>
> <groupId>com.sun.jersey.jersey-test-framework</groupId>
> <artifactId>jersey-test-framework-grizzly</artifactId>
> <version>${jerseyVersion}</version>
> </dependency>
> <dependency>
> <groupId>com.sun.jersey.jersey-test-framework</groupId>
> <artifactId>jersey-test-framework-inmemory</artifactId>
> <version>${jerseyVersion}</version>
> </dependency>
>
> We were using 1.1.5.1 but I bumped it up to 1.3-SNAPSHOT where the  
> problem (threads hanging afterwards) persisted.
>
> > > SelectorThreads are spun per object spawned by the Factory that  
> are
> > > asked for @Before each resource test. That is, each test spins a
> > > thread and the "suite" falls on its face.
> > >
> >
> > The @After method will call this:
> >
> >          public void stop() {
> >              LOGGER.info("Stopping the Grizzly Web Container...");
> >              webServer.stop();
> >              webServer.getSelectorThread().stopEndpoint();
> >          }
>
> I saw this as well but YourKit is showing threads lingering. Bumping  
> the version to 1.3-SNAPSHOT after some pom massaging did not resolve  
> this.
>
Can you confirm that the lingering threads are associated with  
Grizzly? If so we can log a bug against Grizzly.
> > > Unfortunately, the InMemoryTestContainer (desirable: skips the  
> HTTP
> > > portion, focuses on the resources, a lot quicker) does not "see"
> > > provider classes
> >
> > Can you describe a bit more about that?
>
> I'm not too familiar with the jersey test framework so hopefully  
> this log output will better describe the problem I am experiencing:
>
> public class AbstractResourceTest extends JerseyTest {
> 	...
>     @Override
>     protected AppDescriptor configure () {
>         return new  
> WebAppDescriptor 
> .Builder 
> ("com 
> .primalfusion 
> .platformapi 
> .resource 
> ").contextPath("platformApi").contextParam("contextConfigLocation",  
> "classpath:platformApiTest- 
> appContext 
> .xml 
> ").servletClass 
> (SpringServlet 
> .class).contextListenerClass(ContextLoaderListener.class).build();
>     }
>
>     @Override
>     protected TestContainerFactory getTestContainerFactory () {
>         return new GrizzlyWebTestContainerFactory();
>     	//return new InMemoryTestContainerFactory();
>     }
> 	...
> }
>
> Beginning output from using InMemoryTestContainerFactory() (more  
> verbose error messaging than previous version that gives off a big  
> hint about spring configuration (or lack thereof)):
>
> May 31, 2010 2:15:31 PM  
> com.sun.jersey.api.core.PackagesResourceConfig init
> INFO: Scanning for root resource and provider classes in the packages:
>   com.primalfusion.platformapi.resource
> May 31, 2010 2:15:31 PM  
> com.sun.jersey.api.core.ScanningResourceConfig logClasses
> INFO: Root resource classes found:
>   class com.primalfusion.platformapi.resource.SystemResource
>   class com.primalfusion.platformapi.resource.UserDomainsResource
>   class com.primalfusion.platformapi.resource.DomainConceptsResource
>   class com.primalfusion.platformapi.resource.IndexResource
>   class com.primalfusion.platformapi.resource.ActionsResource
>   class com.primalfusion.platformapi.resource.DomainsResource
>   class com.primalfusion.platformapi.resource.DomainOverviewResource
>   class com.primalfusion.platformapi.resource.DomainResource
>   class com.primalfusion.platformapi.resource.TestHelperResource
>   class com.primalfusion.platformapi.resource.DomainConceptResource
>   class com.primalfusion.platformapi.resource.DomainQueryResource
> May 31, 2010 2:15:31 PM  
> com.sun.jersey.api.core.ScanningResourceConfig init
> INFO: No provider classes found.
> May 31, 2010 2:15:31 PM  
> com 
> .sun 
> .jersey 
> .test.framework.spi.container.inmemory.InMemoryTestContainerFactory 
> $InMemoryTestContainer <init>
> INFO: Creating low level InMemory test container configured at the  
> base URI http://localhost:9998/
> May 31, 2010 2:15:31 PM  
> com 
> .sun 
> .jersey 
> .test.framework.spi.container.inmemory.InMemoryTestContainerFactory 
> $InMemoryTestContainer start
> INFO: Starting low level InMemory test container
> May 31, 2010 2:15:31 PM  
> com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
> INFO: Initiating Jersey application, version 'Jersey: 1.3-SNAPSHOT  
> 05/28/2010 12:13 AM'
> May 31, 2010 2:15:32 PM com.sun.jersey.spi.inject.Errors  
> processErrorMessages
> SEVERE: The following errors have been detected with resource and/or  
> provider classes:
>   SEVERE: Missing dependency for constructor public  
> com 
> .primalfusion 
> .platformapi 
> .resource 
> .ActionsResource 
> (com.primalfusion.platformapi.service.PlatformContext) at parameter  
> index 0
>   SEVERE: Missing dependency for constructor public  
> com 
> .primalfusion 
> .platformapi 
> .resource 
> .DomainConceptResource 
> (com.primalfusion.platformapi.service.PlatformContext) at parameter  
> index 0
>   SEVERE: Missing dependency for constructor public  
> com 
> .primalfusion 
> .platformapi 
> .resource 
> .DomainConceptsResource 
> (com.primalfusion.platformapi.service.PlatformContext) at parameter  
> index 0
>   SEVERE: Missing dependency for constructor public  
> com 
> .primalfusion 
> .platformapi 
> .resource 
> .DomainOverviewResource 
> (com.primalfusion.platformapi.service.PlatformContext) at parameter  
> index 0
>   SEVERE: Missing dependency for constructor public  
> com 
> .primalfusion 
> .platformapi 
> .resource 
> .DomainQueryResource 
> (com.primalfusion.platformapi.service.PlatformContext) at parameter  
> index 0
>   SEVERE: Missing dependency for constructor public  
> com 
> .primalfusion 
> .platformapi 
> .resource 
> .DomainResource 
> (com.primalfusion.platformapi.service.PlatformContext) at parameter  
> index 0
>   SEVERE: Missing dependency for constructor public  
> com 
> .primalfusion 
> .platformapi 
> .resource 
> .DomainsResource 
> (com.primalfusion.platformapi.service.PlatformContext) at parameter  
> index 0
>   SEVERE: Missing dependency for field: javax.servlet.ServletContext  
> com.primalfusion.platformapi.resource.SystemResource.context
>   SEVERE: Missing dependency for constructor public  
> com 
> .primalfusion 
> .platformapi 
> .resource 
> .SystemResource 
> (com.primalfusion.platformapi.service.PlatformContext) at parameter  
> index 0
>   SEVERE: Missing dependency for constructor public  
> com 
> .primalfusion 
> .platformapi 
> .resource 
> .UserDomainsResource 
> (com.primalfusion.platformapi.service.PlatformContext) at parameter  
> index 0
> 	...
>
> Beginning output from using GrizzlyWebTestContainerFactory():
>
> May 31, 2010 2:23:15 PM  
> com 
> .sun 
> .jersey 
> .test 
> .framework.spi.container.grizzly.web.GrizzlyWebTestContainerFactory 
> $GrizzlyWebTestContainer <init>
> INFO: Creating Grizzly Web Container configured at the base URI http://localhost:9998/platformApi
> May 31, 2010 2:23:16 PM  
> com 
> .sun 
> .jersey 
> .test 
> .framework.spi.container.grizzly.web.GrizzlyWebTestContainerFactory 
> $GrizzlyWebTestContainer start
> INFO: Starting the Grizzly Web Container...
> May 31, 2010 2:23:16 PM  
> com.sun.grizzly.http.servlet.ServletContextImpl log
> INFO: Initializing Spring root WebApplicationContext
> 2010-05-31 14:23:17 INFO  util.LoggingPropertyPlaceholderConfigurer  
> - Loading properties file from class path resource  
> [platform.properties]
> May 31, 2010 2:23:17 PM com.sun.grizzly.Controller logVersion
> INFO: Starting Grizzly Framework 1.9.18-i - Mon May 31 14:23:17 EDT  
> 2010
> GET: /domains/8888/concepts/(1000000017,1000002071) (application/json)
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.api.core.PackagesResourceConfig init
> INFO: Scanning for root resource and provider classes in the packages:
>   com.primalfusion.platformapi.resource
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.api.core.ScanningResourceConfig logClasses
> INFO: Root resource classes found:
>   class com.primalfusion.platformapi.resource.DomainResource
>   class com.primalfusion.platformapi.resource.DomainQueryResource
>   class com.primalfusion.platformapi.resource.UserDomainsResource
>   class com.primalfusion.platformapi.resource.ActionsResource
>   class com.primalfusion.platformapi.resource.DomainConceptsResource
>   class com.primalfusion.platformapi.resource.DomainsResource
>   class com.primalfusion.platformapi.resource.TestHelperResource
>   class com.primalfusion.platformapi.resource.DomainOverviewResource
>   class com.primalfusion.platformapi.resource.DomainConceptResource
>   class com.primalfusion.platformapi.resource.SystemResource
>   class com.primalfusion.platformapi.resource.IndexResource
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.api.core.ScanningResourceConfig init
> INFO: No provider classes found.
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.servlet.SpringServlet getContext
> INFO: Using default applicationContext
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, DomainConceptsResource, of type  
> com.primalfusion.platformapi.resource.DomainConceptsResource as a  
> root resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, domainOverviewResource, of type  
> com.primalfusion.platformapi.resource.DomainOverviewResource as a  
> root resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, domainResource, of type  
> com.primalfusion.platformapi.resource.DomainResource as a root  
> resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, indexResource, of type  
> com.primalfusion.platformapi.resource.IndexResource as a root  
> resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, SystemResource, of type  
> com.primalfusion.platformapi.resource.SystemResource as a root  
> resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, actionsResource, of type  
> com.primalfusion.platformapi.resource.ActionsResource as a root  
> resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, domainQueryResource, of type  
> com.primalfusion.platformapi.resource.DomainQueryResource as a root  
> resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, domainConceptResource, of type  
> com.primalfusion.platformapi.resource.DomainConceptResource as a  
> root resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, DomainsResource, of type  
> com.primalfusion.platformapi.resource.DomainsResource as a root  
> resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, userDomainsResource, of type  
> com.primalfusion.platformapi.resource.UserDomainsResource as a root  
> resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, webApplicationExceptionMapper, of  
> type com.primalfusion.platformapi.util.WebApplicationExceptionMapper  
> as a provider class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, unsupportedFormatExceptionMapper, of  
> type  
> com.primalfusion.platformapi.util.UnsupportedFormatExceptionMapper  
> as a provider class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, illegalArgumentExceptionMapper, of  
> type  
> com.primalfusion.platformapi.util.IllegalArgumentExceptionMapper as  
> a provider class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, defaultExceptionMapper, of type  
> com.primalfusion.platformapi.util.DefaultExceptionMapper as a  
> provider class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, WebApplicationExceptionMapper, of  
> type com.primalfusion.platformapi.util.WebApplicationExceptionMapper  
> as a provider class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.spi.spring.container.SpringComponentProviderFactory  
> register
> INFO: Registering Spring bean, testHelperResource, of type  
> com.primalfusion.platformapi.resource.TestHelperResource as a root  
> resource class
> May 31, 2010 2:23:17 PM  
> com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
> INFO: Initiating Jersey application, version 'Jersey: 1.3-SNAPSHOT  
> 05/28/2010 12:13 AM'
> 2010-05-31 14:23:17 INFO  service.PlatformContext - Creating new  
> instance of class com.primalfusion.platformapi.service.PlatformContext
> 	...
>
> > > (even though it sees the root resources via spring injected
> > > context.xml) out of the box so a quick TestContainerFactory swap
> > > won't work. I suspect differences between WebAppDescriptor and
> > > LowLevelDescriptor is at fault.
> > >
> >
> > Yes, there are some issues related to the transformation, it  
> should be
> > more robust in reporting errors as it is not possible to map from  
> web
> > to low level in all cases. But i am not sure the provider stuff is
> > related to this.
>
> Based on the log output above I'd say it has nothing to do with  
> provider resources either since both GrizzlyWebTestContainer and  
> InMemoryTestContainer both INFO: No provider classes found.
>
> > > My question is what are the best practices for writing test suites
> > > of this sort using the JerseyTest framework and JUnit 4? Currently
> > > the only annotations that are employed are @Test, @Before and
> > > @After.  Ideally we'd like each test to be part of a suite of  
> tests
> > > that has a WebTestContainer created at the beginning of the entire
> > > suite of tests rather than each individual test and have the
> > > WebAppDescriptor replaced @Before each individual @Test.
> > >
> >
> > Currently JerseyTest is a bit limited in this respect. I think  
> what we
> > require is an AbstractJerseyTest from which you can extend and  
> decide
> > on the policy of starting and stopping the test container.
>
> This sounds like an excellent idea!
>
> > I think the only way you can control this at the moment is to right
> > your own test container factory to control stop and start per test
> > class instantiation.
> >
> > Any thoughts Pavel?
>
> Other than the source provided in the jersey-test-framework itself  
> are there any examples floating around the web of such customized  
> TestContainerFactories?
No.
> A workaround idea was to have a factory that returns the same  
> WebServer but resetting it each time.
>
Yes, that could be a good solution to work around until we fix stuff.
Paul.
> > As for a suite of tests that is be a little different to what we are
> > used to. If you can give an example of how you would like to write
> > your code we might be able to use that as a template to support that
> > style.
> >
> > Paul.
>
> Here are some test cases:
>
> 	@Test
> 	public void testGetJsonSucceeds()
> 	{
> 		ClientResponse response = callGet( path,  
> MediaType.APPLICATION_JSON_TYPE );
> 		validateResponse( 200, MediaType.APPLICATION_JSON_TYPE, response );
> 		String body = response.getEntity( String.class );
> 		assertTrue( body.contains( validJson ) );
> 	}
>
> 	@Test
> 	public void testGetHtmlSucceeds()
> 	{
> 		ClientResponse response = callGet( path, MediaType.TEXT_HTML_TYPE );
> 		validateResponse( 200, MediaType.TEXT_HTML_TYPE, response );
> 		 
> assertTrue( response.getEntity( String.class ).contains( "<td>Name</ 
> td><td>FE_Demo</td>" ) );
> 	}
>
> 	@Test
> 	public void testGetDefaultsToJson()
> 	{
> 		ClientResponse response = callGet( path, MediaType.WILDCARD_TYPE );
> 		validateResponse( 200, MediaType.APPLICATION_JSON_TYPE, response );
> 	}
>
> 	@Test
> 	public void testPutFails()
> 	{
> 		ClientResponse response = callPut( path, validJson,  
> MediaType.APPLICATION_JSON_TYPE );
> 		assertEquals( 405, response.getStatus() );
> 	}
>
> These tests are very simple and specific, each testing a very narrow  
> aspect of the PURL layer. The general form is: make one request to  
> some URL, inspect the result, assert expectations. We want many of  
> these simple, hyper-focused tests rather than a handful of  
> complicated rambling ones.
>
> With hundreds or thousands of short tests, the time overhead  
> incurred in setup and teardown per test is too costly (not to  
> mention the environment leaks resources as it is cycled anew for  
> each test).
>
> We'd like to take advantage of JUnit4's parameterized test framework  
> that can operate on large cartesian products of test cases - this is  
> simply not viable from the incurred overhead of jersey setting up  
> and tearing down per test at the moment unfortunately using the  
> GrizzlyWebTestContainer.
>
> Thanks again,
>
> Bartosz Bobnis
> Software Developer
> Primal