package org.jboss.resteasy.test.cdi.injection; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.logging.Logger; import org.jboss.resteasy.category.NotForWildFly9; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionBook; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionBookBag; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionBookBagLocal; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionBookCollection; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionBookMDB; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionBookReader; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionBookResource; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionBookWriter; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionDependentScoped; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionNewBean; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionResourceBinding; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionResourceProducer; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionStatefulEJB; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionStereotypedApplicationScope; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionStereotypedDependentScope; import org.jboss.resteasy.test.cdi.injection.resource.CDIInjectionUnscopedResource; import org.jboss.resteasy.test.cdi.injection.resource.ReverseInjectionEJBHolder; import org.jboss.resteasy.test.cdi.injection.resource.ReverseInjectionEJBHolderLocal; import org.jboss.resteasy.test.cdi.injection.resource.ReverseInjectionEJBHolderRemote; import org.jboss.resteasy.test.cdi.injection.resource.ReverseInjectionEJBInterface; import org.jboss.resteasy.test.cdi.injection.resource.ReverseInjectionResource; import org.jboss.resteasy.test.cdi.injection.resource.StatefulApplicationScopedEJBwithJaxRsComponents; import org.jboss.resteasy.test.cdi.injection.resource.StatefulApplicationScopedEJBwithJaxRsComponentsInterface; import org.jboss.resteasy.test.cdi.injection.resource.StatefulDependentScopedEJBwithJaxRsComponents; import org.jboss.resteasy.test.cdi.injection.resource.StatefulDependentScopedEJBwithJaxRsComponentsInterface; import org.jboss.resteasy.test.cdi.injection.resource.StatefulRequestScopedEJBwithJaxRsComponents; import org.jboss.resteasy.test.cdi.injection.resource.StatefulRequestScopedEJBwithJaxRsComponentsInterface; import org.jboss.resteasy.test.cdi.injection.resource.StatelessEJBwithJaxRsComponents; import org.jboss.resteasy.test.cdi.injection.resource.StatelessEJBwithJaxRsComponentsInterface; import org.jboss.resteasy.test.cdi.util.Constants; import org.jboss.resteasy.test.cdi.util.Counter; import org.jboss.resteasy.test.cdi.util.PersistenceUnitProducer; import org.jboss.resteasy.test.cdi.util.Utilities; import org.jboss.resteasy.test.cdi.util.UtilityProducer; import org.jboss.resteasy.util.HttpResponseCodes; import org.jboss.resteasy.utils.PermissionUtil; import org.jboss.resteasy.utils.PortProviderUtil; import org.jboss.resteasy.utils.TestUtil; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; import javax.naming.Context; import javax.naming.InitialContext; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.GenericType; import javax.ws.rs.core.Response; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.ParameterizedType; import java.lang.reflect.ReflectPermission; import java.lang.reflect.Type; import java.util.Collection; import java.util.Hashtable; import java.util.Iterator; import java.util.PropertyPermission; import static junit.framework.TestCase.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** * @tpSubChapter CDI * @tpChapter Integration tests * @tpTestCaseDetails ReverseInjectionTest goes beyond InjectionTest by injecting Resteasy objects * into other kinds of beans, e.g., EJBs. For example, * *) an EJB called ReverseInjectionEJBHolder is injected into the Resteasy resource ReverseInjectionResource * *) a variety of EJBs, e.g., StatelessEJBwithJaxRsComponents, are injected into ReverseInjectionEJBHolder * *) a variety of Resteasy resources are injected into StatelessEJBwithJaxRsComponents and similar EJBs. * Also, the EJBs like StatelessEJBwithJaxRsComponents are injected into ReverseInjectionEJBHolder using both. * Annotation @EJB and @Inject, and the semantics of both are tested. * @tpSince RESTEasy 3.0.16 */ @RunWith(Arquillian.class) @Category(NotForWildFly9.class) //fails on 9.x due to: [WFLY-3355] MDB fails to deploy on reload public class ReverseInjectionTest extends AbstractInjectionTestBase { private static Logger log = Logger.getLogger(ReverseInjectionTest.class); Client client; @Before public void init() { client = ClientBuilder.newClient(); } @After public void close() { client.close(); } static ParameterizedType BookCollectionType = new ParameterizedType() { @Override public Type[] getActualTypeArguments() { return new Type[]{CDIInjectionBook.class}; } @Override public Type getRawType() { return Collection.class; } @Override public Type getOwnerType() { return null; } }; @Deployment public static Archive<?> createTestArchive() { WebArchive war = TestUtil.prepareArchive("resteasy-reverse-injection-test") .addClasses(AbstractInjectionTestBase.class, ReverseInjectionTest.class, PortProviderUtil.class) .addClasses(Constants.class, PersistenceUnitProducer.class, UtilityProducer.class, Utilities.class) .addClasses(CDIInjectionBook.class, CDIInjectionBookResource.class) .addClasses(CDIInjectionResourceBinding.class, CDIInjectionResourceProducer.class) .addClasses(Counter.class, CDIInjectionBookCollection.class, CDIInjectionBookReader.class, CDIInjectionBookWriter.class) .addClasses(CDIInjectionDependentScoped.class, CDIInjectionStatefulEJB.class, CDIInjectionUnscopedResource.class) .addClasses(CDIInjectionBookBagLocal.class, CDIInjectionBookBag.class) .addClasses(CDIInjectionBookMDB.class) .addClasses(ReverseInjectionEJBInterface.class) .addClasses(StatelessEJBwithJaxRsComponentsInterface.class, StatelessEJBwithJaxRsComponents.class) .addClasses(StatefulDependentScopedEJBwithJaxRsComponentsInterface.class, StatefulDependentScopedEJBwithJaxRsComponents.class) .addClasses(StatefulRequestScopedEJBwithJaxRsComponentsInterface.class, StatefulRequestScopedEJBwithJaxRsComponents.class) .addClasses(StatefulApplicationScopedEJBwithJaxRsComponentsInterface.class, StatefulApplicationScopedEJBwithJaxRsComponents.class) .addClasses(ReverseInjectionEJBHolderRemote.class, ReverseInjectionEJBHolderLocal.class, ReverseInjectionEJBHolder.class) .addClasses(ReverseInjectionResource.class) .addClasses(CDIInjectionNewBean.class, CDIInjectionStereotypedApplicationScope.class, CDIInjectionStereotypedDependentScope.class) .addClass(NotForWildFly9.class) //required as this test is not @RunAsClient annotated .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") .addAsResource(ReverseInjectionTest.class.getPackage(), "persistence.xml", "META-INF/persistence.xml"); // Arquillian in the deployment war.addAsManifestResource(PermissionUtil.createPermissionsXmlAsset(new ReflectPermission("suppressAccessChecks"), new RuntimePermission("accessDeclaredMembers"), new PropertyPermission("arquillian.*", "read")), "permissions.xml"); return war; } private String generateURL(String path) { return PortProviderUtil.generateURL(path, "resteasy-reverse-injection-test"); } /** * @tpTestDetails Addresses injection of JAX-RS components (BookResource, BookReader, BookWriter) into * a stateless EJB3. The target SLSB is not a contextual object, since it is * obtained through JNDI, so CDI performs injections when the SLSB is created, * but there is no scope management. It follows that the target SLSB is not recreated * for the second invocation. * @tpSince RESTEasy 3.0.16 */ @Test public void testSLSB() throws Exception { log.info("starting testSLSB()"); final Hashtable<String, String> jndiProperties = new Hashtable<String, String>(); jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); final Context context = new InitialContext(jndiProperties); String name = "java:global/resteasy-reverse-injection-test/StatelessEJBwithJaxRsComponents!" + StatelessEJBwithJaxRsComponentsInterface.class.getName(); StatelessEJBwithJaxRsComponentsInterface remote = StatelessEJBwithJaxRsComponentsInterface.class.cast(context.lookup(name)); assertNotNull("Bean should not be null", remote); log.info("remote: " + remote.toString()); remote.setUp(ReverseInjectionResource.NON_CONTEXTUAL); assertTrue("Call bean method faild", remote.test(ReverseInjectionResource.NON_CONTEXTUAL)); } /** * @tpTestDetails Addresses injection of JAX-RS components (BookResource, BookReader, BookWriter) into * a @Dependent annotated stateful EJB3. The target SFSB is not a contextual object, * since it is obtained through JNDI, so CDI performs injections when the SFSB is created, * but there is no scope management. It follows that the target SFSB is not recreated * for the second invocation. * @tpSince RESTEasy 3.0.16 */ @Test public void testSFSBDependentScope() throws Exception { log.info("starting testSFSBDependentScope()"); doTestSFSB("Dependent"); } /** * @tpTestDetails Addresses injection of JAX-RS components (BookResource, BookReader, BookWriter) into * a @RequestScoped annotated stateful EJB3. The target SFSB is not a contextual object, * since it is obtained through JNDI, so CDI performs injections when the SFSB is created, * but there is no scope management. It follows that the target SFSB is not recreated * for the second invocation. * @tpSince RESTEasy 3.0.16 */ @Test public void testSFSBRequestScope() throws Exception { log.info("starting testSFSBRequestScope()"); doTestSFSB("Request"); } /** * @tpTestDetails Addresses injection of JAX-RS components (BookResource, BookReader, BookWriter) into * a @ApplicationScoped annotated stateful EJB3. The target SFSB is not a contextual object, * since it is obtained through JNDI, so CDI performs injections when the SFSB is created, * but there is no scope management. It follows that the target SFSB is not recreated * for the second invocation. * @tpSince RESTEasy 3.0.16 */ @Test public void testSFSBApplicationScope() throws Exception { log.info("starting testSFSBApplicationScope()"); doTestSFSB("Application"); } private void doTestSFSB(String scope) throws Exception { final Hashtable<String, String> jndiProperties = new Hashtable<String, String>(); jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); final Context context = new InitialContext(jndiProperties); String className = "Stateful" + scope + "ScopedEJBwithJaxRsComponents"; Class<?> viewName = Class.forName("org.jboss.resteasy.test.cdi.injection.resource." + className + "Interface"); String lookup = "java:global/resteasy-reverse-injection-test/" + className + "!" + viewName.getName(); log.info("lookup: " + lookup); ReverseInjectionEJBInterface remote = ReverseInjectionEJBInterface.class.cast(context.lookup(lookup)); log.info("remote: " + remote); remote.setUp(ReverseInjectionResource.NON_CONTEXTUAL); assertTrue("Call bean method faild", remote.test(ReverseInjectionResource.NON_CONTEXTUAL)); } /** * @tpTestDetails Verifies the scopes of the EJBs used in this set of tests. * @tpSince RESTEasy 3.0.16 */ @Test public void testEJBHolderInResourceScopes() throws Exception { WebTarget base = client.target(generateURL("/reverse/testScopes/")); Response response = base.request().post(Entity.text(new String())); assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); response.close(); } /** * @tpTestDetails Test static hash map in RequestScoped bean used as REST point. * @tpSince RESTEasy 3.0.16 */ @Test public void testEJBHolderInResource() throws Exception { WebTarget base = client.target(generateURL("/reverse/setup/")); Response response = base.request().post(Entity.text(new String())); assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); response.close(); base = client.target(generateURL("/reverse/test/")); response = base.request().post(Entity.text(new String())); assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); response.close(); } /** * @tpTestDetails Tests the injection of a JAX-RS resource (BookResource) into an MDB. * @tpSince RESTEasy 3.0.16 */ @Test public void testMDB() throws Exception { String destinationName = "queue/test"; Context ic; ConnectionFactory cf; Connection connection = null; try { ic = new InitialContext(); cf = (ConnectionFactory) ic.lookup("/ConnectionFactory"); Queue queue = (Queue) ic.lookup(destinationName); connection = cf.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = session.createProducer(queue); connection.start(); CDIInjectionBook book1 = new CDIInjectionBook("Dead Man Snoring"); TextMessage message = session.createTextMessage(book1.getName()); producer.send(message); log.info("Message sent to to the JMS Provider: " + book1.getName()); CDIInjectionBook book2 = new CDIInjectionBook("Dead Man Drooling"); message = session.createTextMessage(book2.getName()); producer.send(message); log.info("Message sent to to the JMS Provider: " + book2.getName()); WebTarget base = client.target(generateURL("/mdb/books")); Response response = base.request().get(); log.info("status: " + response.getStatus()); assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); @SuppressWarnings("unchecked") Collection<CDIInjectionBook> books = response.readEntity(new GenericType<>(BookCollectionType)); log.info("Collection: " + books); assertEquals("Wrong count of received items", 2, books.size()); Iterator<CDIInjectionBook> it = books.iterator(); CDIInjectionBook b1 = it.next(); CDIInjectionBook b2 = it.next(); assertTrue("Book is not inject correctly", book1.equals(b1) && book2.equals(b2) || book1.equals(b2) && book2.equals(b1)); } catch (Exception exc) { StringWriter errors = new StringWriter(); exc.printStackTrace(new PrintWriter(errors)); log.error(errors.toString()); } finally { if (connection != null) { try { connection.close(); } catch (JMSException e) { StringWriter errors = new StringWriter(); e.printStackTrace(new PrintWriter(errors)); log.error(errors.toString()); } } } } }