Skip to content
This repository has been archived by the owner on Jun 14, 2018. It is now read-only.

Commit

Permalink
Temporary solution for issue 26
Browse files Browse the repository at this point in the history
It is almost complete. Here is what is pending to be done:

1. Review carefully JAX-RS 2.0 specification to make sure everything is in compliance and designed accordingly.
1. Add some meaningful comments around the code that implement this feature.
1. Add a sample test case (using an additional JAX-RS application class) to the sample application. This application should have its own resources (two non Spring bean classes), to be registered manually, and should not include the Echo resource, which is a Spring bean. One of its resource should be added as class and the other as singleton. Both should work fine.
1. Integration test to assure item 1 works perfectly in the sample application.
1. Integration test to assure the two resources registered manually do not get included to the original application, which should still have only the Echo resource only.
1. Add an item to mention this feature in the features list int the README md file.
1. Add an section to describe with details this feature in the USAGE md file.
  • Loading branch information
fabiocarvalho777 committed May 18, 2017
1 parent f9fcfdf commit cc813b6
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ private GenericBeanDefinition createApplicationServlet(Class<? extends Applicati
applicationServletBean.setFactoryBeanName(ResteasyApplicationBuilder.BEAN_NAME);
applicationServletBean.setFactoryMethodName("build");

Set<Class<?>> resources = allResources;
Set<Class<?>> resources = getApplicationResourceClasses(applicationClass);

ConstructorArgumentValues values = new ConstructorArgumentValues();
values.addIndexedArgumentValue(0, applicationClass.getName());
Expand All @@ -316,4 +316,46 @@ private GenericBeanDefinition createApplicationServlet(Class<? extends Applicati
return applicationServletBean;
}

private Set<Class<?>> getApplicationResourceClasses(Class<? extends Application> applicationClass) {
Application application;

try {
application = applicationClass.newInstance();
} catch (Exception e) {
logger.warn("Not able to identify specific application class (" + applicationClass.getSimpleName() + ") resources, returning all instead", e);
return allResources;
}

Set<Class<?>> classes = application.getClasses();
Set<Object> singletons = application.getSingletons();

if ((classes == null || classes.size() == 0) && (singletons == null || singletons.size() == 0)) {
// This should be the case for most applications, which relies on resources scanning,
// instead of manually registering the resources
return allResources;
}

Set<Class<?>> resources = new HashSet<Class<?>>();

if(classes != null) {
for(Class clazz : classes) {
if(AnnotationUtils.findAnnotation(clazz, Path.class) != null) {
resources.add(clazz);
}
}
}

if(singletons != null) {
for(Object singleton : singletons) {
if(AnnotationUtils.findAnnotation(singleton.getClass(), Path.class) != null) {
resources.add(singleton.getClass());
}
}
}

logger.debug("Application class " + applicationClass.getSimpleName() + " has " + resources.size() + " specific resources");

return resources;
}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
package com.paypal.springboot.resteasy;

import com.paypal.springboot.resteasy.sample.TestApplication1;
import com.paypal.springboot.resteasy.sample.TestResource1;
import com.paypal.springboot.resteasy.sample.TestResource2;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
import org.testng.annotations.Test;

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

import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
import static org.testng.Assert.*;

/**
* Created by facarvalho on 11/25/15.
Expand All @@ -21,23 +36,63 @@ public class ResteasyEmbeddedServletInitializerTest extends AbstractTestNGSpring
private ApplicationContext applicationContext;

@Test
public void postProcessBeanFactory() {
public void servletsRegistrationTest() {
Map<String, ServletRegistrationBean> servletRegistrationBeans = applicationContext.getBeansOfType(ServletRegistrationBean.class);
Assert.assertNotNull(servletRegistrationBeans);
assertNotNull(servletRegistrationBeans);

// Although there are 5 sample JAX-RS Application classes, one of them is not annotated with the ApplicationPath annotation!
Assert.assertEquals(servletRegistrationBeans.size(), 4);
assertEquals(servletRegistrationBeans.size(), 4);

for(String applicationClassName : servletRegistrationBeans.keySet()) {
testApplicaton(applicationClassName, servletRegistrationBeans.get(applicationClassName));
}
}

private void testApplicaton(String applicationClassName, ServletRegistrationBean servletRegistrationBean) {
Assert.assertEquals(applicationClassName, servletRegistrationBean.getServletName());
Assert.assertTrue(servletRegistrationBean.isAsyncSupported());
Assert.assertEquals(applicationClassName, servletRegistrationBean.getInitParameters().get("javax.ws.rs.Application"));
Assert.assertTrue(servletRegistrationBean.isAsyncSupported());
assertEquals(applicationClassName, servletRegistrationBean.getServletName());
assertTrue(servletRegistrationBean.isAsyncSupported());
assertEquals(applicationClassName, servletRegistrationBean.getInitParameters().get("javax.ws.rs.Application"));
assertTrue(servletRegistrationBean.isAsyncSupported());
}

@Test
public void manualResourcesRegistrationTest() {

final String appClassName = TestApplication1.class.getName();

ConfigurableListableBeanFactory beanFactoryMock = Mockito.mock(
ConfigurableListableBeanFactory.class,
withSettings().extraInterfaces(BeanDefinitionRegistry.class));

ConfigurableEnvironment configurableEnvironmentMock = Mockito.mock(ConfigurableEnvironment.class);

when(configurableEnvironmentMock.getProperty("resteasy.jaxrs.app.registration")).thenReturn("property");
when(configurableEnvironmentMock.getProperty("resteasy.jaxrs.app.classes")).thenReturn(appClassName);
when(beanFactoryMock.getBean(ConfigurableEnvironment.class)).thenReturn(configurableEnvironmentMock);

ResteasyEmbeddedServletInitializer servletInitializer = new ResteasyEmbeddedServletInitializer();
servletInitializer.postProcessBeanFactory(beanFactoryMock);

ArgumentCaptor<GenericBeanDefinition> beanDefinitionCaptor = ArgumentCaptor.forClass(GenericBeanDefinition.class);
verify((BeanDefinitionRegistry) beanFactoryMock, times(1)).registerBeanDefinition(eq(appClassName), beanDefinitionCaptor.capture());

GenericBeanDefinition beanDefinition = beanDefinitionCaptor.getValue();
assertNotNull(beanDefinition);
assertFalse(beanDefinition.isAutowireCandidate());
assertEquals(beanDefinition.getScope(), "singleton");

Set<Class<?>> providers = new HashSet();
Set<Class<?>> resources = new HashSet();
resources.add(TestResource1.class);
resources.add(TestResource2.class);

ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
assertNotNull(constructorArgumentValues);
assertEquals(constructorArgumentValues.getArgumentCount(), 4);
assertEquals(constructorArgumentValues.getArgumentValue(0, String.class).getValue(), appClassName);
assertEquals(constructorArgumentValues.getArgumentValue(1, String.class).getValue(), "/myapp1");
assertEquals(constructorArgumentValues.getArgumentValue(2, Set.class).getValue(), resources);
assertEquals(constructorArgumentValues.getArgumentValue(3, Set.class).getValue(), providers);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;

/**
* Sample test JAX-RS application.
Expand All @@ -10,4 +12,19 @@
*/
@ApplicationPath("/myapp1")
public class TestApplication1 extends Application {

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

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

}

0 comments on commit cc813b6

Please sign in to comment.