package org.jboss.resteasy.test.providers.jaxb; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAnyElement; import javax.xml.bind.annotation.XmlRootElement; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.RunAsClient; import org.jboss.arquillian.junit.Arquillian; import org.jboss.resteasy.utils.PortProviderUtil; import org.jboss.resteasy.utils.TestUtil; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; /** * @tpSubChapter Jaxb provider * @tpChapter Integration tests * @tpSince RESTEasy 3.0.16 */ @RunWith(Arquillian.class) @RunAsClient public class XmlJAXBContextFinderTest { @Deployment public static Archive<?> deploy() { WebArchive war = TestUtil.prepareArchive(XmlJAXBContextFinderTest.class.getSimpleName()); return TestUtil.finishContainerPrepare(war, null, BeanWrapper.class, FirstBean.class, SecondBean.class, FirstTestResource.class, SecondTestResource.class, MyJAXBContextResolver.class); } @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public static final class BeanWrapper { @XmlAnyElement(lax = true) private Object bean; public Object getBean() { return this.bean; } public void setBean(Object bean) { this.bean = bean; } } @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public static final class FirstBean { private String data; public String getData() { return this.data; } public void setData(String data) { this.data = data; } } @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public static final class SecondBean { private String data; public String getData() { return this.data; } public void setData(String data) { this.data = data; } } @Path("/firstTestResource") @Produces(MediaType.APPLICATION_XML) public static final class FirstTestResource { @GET public Response get() { FirstBean firstBean = new FirstBean(); firstBean.setData("firstTestResource"); BeanWrapper beanWrapper = new BeanWrapper(); beanWrapper.setBean(firstBean); return Response.ok(beanWrapper).build(); } } @Path("/secondTestResource") @Produces(MediaType.APPLICATION_XML) public static final class SecondTestResource { @GET public Response get() { SecondBean secondBean = new SecondBean(); secondBean.setData("secondTestResource"); BeanWrapper beanWrapper = new BeanWrapper(); beanWrapper.setBean(secondBean); return Response.ok(beanWrapper).build(); } } @Provider @Produces(MediaType.APPLICATION_XML) public static class MyJAXBContextResolver implements ContextResolver<JAXBContext> { private JAXBContext jaxbContext; @Override public JAXBContext getContext(Class<?> type) { if (this.jaxbContext == null) { try { this.jaxbContext = JAXBContext.newInstance(BeanWrapper.class, FirstBean.class, SecondBean.class); } catch (JAXBException e) { } } return this.jaxbContext; } } private String generateURL(String path) { return PortProviderUtil.generateURL(path, XmlJAXBContextFinderTest.class.getSimpleName()); } /** * @tpTestDetails In the following test both firstWebTarget and secondWebTarget will share the same XmlJAXBContextFinder * inherited from their shared parent configuration. We define and register a ContextResolver<JAXBContext> for each * webTarget so that firstWebTarget and secondWebTarget have its own (respectively firstJaxbContextResolver * and secondJaxbContextResolver). * @tpSince RESTEasy 3.0.16 */ @Test public void test() { Client client = ClientBuilder.newClient(); try { // First webTarget WebTarget firstWebTarget = client.target(generateURL("/firstTestResource")); ContextResolver<JAXBContext> firstJaxbContextResolver = new ContextResolver<JAXBContext>() { private JAXBContext jaxbContext; @Override public JAXBContext getContext(Class<?> type) { if (this.jaxbContext == null) { try { this.jaxbContext = JAXBContext.newInstance(BeanWrapper.class, FirstBean.class); } catch (JAXBException e) { } } return this.jaxbContext; } }; Response firstResponse = firstWebTarget.register(firstJaxbContextResolver) .request(MediaType.APPLICATION_XML_TYPE).get(); BeanWrapper firstBeanWrapper = firstResponse.readEntity(BeanWrapper.class); Assert.assertTrue("First bean is not assignable from the parent bean", FirstBean.class.isAssignableFrom(firstBeanWrapper.getBean().getClass())); // Second webTarget WebTarget secondWebTarget = client.target(generateURL("/secondTestResource")); // Will never be called ContextResolver<JAXBContext> secondJaxbContextResolver = new ContextResolver<JAXBContext>() { private JAXBContext jaxbContext; @Override public JAXBContext getContext(Class<?> type) { if (this.jaxbContext == null) { try { this.jaxbContext = JAXBContext.newInstance(BeanWrapper.class, SecondBean.class); } catch (JAXBException e) { } } return this.jaxbContext; } }; Response secondResponse = secondWebTarget.register(secondJaxbContextResolver) .request(MediaType.APPLICATION_XML_TYPE).get(); BeanWrapper secondBeanWrapper = secondResponse.readEntity(BeanWrapper.class); Assert.assertTrue("Second bean is not assignable from the parent bean", SecondBean.class.isAssignableFrom(secondBeanWrapper.getBean().getClass())); } finally { client.close(); } } }