Você está na página 1de 9

RESTful Services There are different ways to build RESTful services with CXF. 1.

JAX-RS (JSR-311) - Java API for building RESTful Web Services. 2. JAX-WS Provider and Dispatch 3. HTTP Binding (deprecated) Terminology Resource class A Java class that uses JAX-RS annotations to implement a corresponding Web resource. Root resource class A resource class annotated with @Path. Root resource classes provide the roots of the resource class tree and provide access to sub-resources. Request method designator A runtime annotation annotated with @HttpMethod. Used to identify the HTTP request method to be handled by a resource method. Resource method A method of a resource class annotated with a request method designator that is used to handle requests on the corresponding resource. Sub-resource locator A method of a resource class that is used to locate sub-resources of the corresponding resource. Sub-resource method A method of a resource class that is used to handle requests on a sub-resource of the corresponding resource. Provider An implementation of a JAX-RS extension interface. Providers extend the capabilities of a JAX-RS runtime.

Configuration and Publication A JAX-RS application consists of one or more resources and zero or more providers. They are configured via an application-supplied subclass of Application. For example, see BookApplication.java. An implementation MAY provide alternate mechanisms for locating resource classes and providers (e.g. runtime class scanning) but use of Application is the only portable means of configuration.

Applications are published in different ways depending on whether the application is run in a Java SE environment or within a container. [A] Java SE environment In a Java SE environment a configured instance of an endpoint class can be obtained using the createEndpoint method of RuntimeDelegate. The application supplies an instance of Application and the type of endpoint required. An implementation MAY support zero or more endpoint types of any desired type. How the resulting endpoint class instance is used to publish the application is outside the scope of this specification. JAX-RS RuntimeDelegate and Applications The CXF endpoint type is JAXRSServerFactoryBean. If you have a JAX-RS Application implementation available, the JAX-RS RuntimeDelegate can be used to minimize the interaction with the CXF JAX-RS specific API. The CustomApplication is a subclass of Application and has a @ApplicationPath value.
import javax.ws.rs.ext.RuntimeDelegate; import org.apache.cxf.endpoint.Server; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; RuntimeDelegate delegate = RuntimeDelegate.getInstance(); JAXRSServerFactoryBean bean = delegate.createEndpoint(new CustomApplication(), JAXRSServerFactoryBean.class); // before CXF 2.3.1 : // bean.setAddress("http://localhost:8080/services"); bean.setAddress("http://localhost:8080/services" + bean.getAddress()); Server server = bean.create(); server.start(); // and finally server.stop();

Configuring JAX-RS services programmatically

The following is a configuration using the CXF endpoint that does not rely on Application. The resource is added directly to the endpoint.
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; ... JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); sf.setResourceClasses(CustomerService.class); sf.setAddress("http://localhost:9000/"); sf.create();

The JAXRSServerFactoryBean creates a Server inside CXF which starts listening for requests on the URL specified. You can add multiple root resources to the endpoint. setResourceClasses() is for root resources only, use setProvider() or setProviders() for @Provider annotated classes. By default, the JAX-RS runtime is responsible for the lifecycle of resource classes, default lifecycle is per-request. You can set the lifecycle to singleton by using following line:
sf.setResourceProvider(BookStore.class, new SingletonResourceProvider(new BookStore()));

If you prefer not to let the JAX-RS runtime handle the resource class lifecycle for you (for example, it might be the case that your resource class is created by other containers such as Spring), you can do the following:
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); CustomerService cs = new CustomerService(); sf.setServiceBeans(cs); sf.setAddress("http://localhost:9080/"); sf.create();

An implementation that supports publication via JAX-WS MUST support createEndpoint with an endpoint type of javax.xml.ws.Provider. JAX-WS describes how a Provider based endpoint can be published in an SE environment. Configuring JAX-RS endpoints programmatically without Spring

Note that even though no Spring is explicitly used in the previous section, it is still used by default to have various CXF components registered with the bus such as transport factories. If no Spring libraries are available on the classpath then please follow the following example :
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); sf.setResourceClasses(CustomerService.class); sf.setResourceProvider(CustomerService.class, new SingletonResourceProvider(new CustomerService())); sf.setAddress("http://localhost:9000/"); BindingFactoryManager manager = sf.getBus().getExtension(BindingFactoryManager.class); JAXRSBindingFactory factory = new JAXRSBindingFactory(); factory.setBus(sf.getBus()); manager.registerBindingFactory(JAXRSBindingFactory.JAXRS_BINDING_ID, factory); sf.create();

Configuring JAX-RS services programmatically with Spring configuration file When using Spring explicitly in your code, you may want to follow this example :
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"/org/apache/cxf/jaxrs/spring/servers.xml"}); // 'simple' is the id of the jaxrs server bean JAXRSServerFactoryBean sfb = (JAXRSServerFactoryBean)ctx.getBean("simple"); sfb.create();

Note that in in this case your Spring configuration file should import cxf-extension-http-jetty.xml instead of cxf-servlet.xml:
<!-- <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> --> <import resource="classpath:META-INF/cxf/cxf-extension-http-jetty.xml" />

[B] Servlet It is RECOMMENDED that implementations support the Servlet 3 framework pluggability mechanism to enable portability between containers and to avail themselves of container-supplied class scanning facilities. When using the pluggability mechanism the following conditions MUST be met:

(1) If no Application subclass is present the added servlet MUST be named javax.ws.rs.core.Application and all root resource classes and providers packaged in the web application MUST be included in the published JAX-RS application. The application MUST be packaged with a web.xml that specifies a servlet mapping for the added servlet. (2) If an Application subclass is present and there is already a servlet defined that has a servlet initialization parameter named javax.ws.rs.Application whose value is the fully qualified name of the Application subclass then no new servlet should be added by the JAX-RS implementations ContainerInitializer since the application is already being handled by an existing servlet.
<servlet> <servlet-name>CXFServlet</servlet-name> <display-name>CXF Servlet</display-name> <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>org.apache.cxf.systest.jaxrs.BookApplication</param-value> </init-param> <!-This parameter is recognized only starting from CXF 2.3.1 @ApplicationPath value will be ignored if this parameter is set to true --> <init-param> <param-name>jaxrs.application.address.ignore</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>

(3) If an Application subclass is present that is not being handled by an existing servlet then the servlet added by the ContainerInitializer MUST be named with the fully qualified name of the Application subclass. If the Application subclass is annotated with @ApplicationPath and no servlet-mapping exists for the added servlet then a new servlet mapping is added with the value of the @ApplicationPath annotation with /* appended otherwise the existing mapping is used. If the Application subclass is not annotated with @ApplicationPath then the application MUST be packaged with a web.xml that specifies a servlet mapping for the added servlet. It is an error for more than one application to be deployed at the same effective servlet mapping

In either of the latter two cases, if both Application.getClasses and Application.getSingletons return an empty list then all root resource classes and providers packaged in the web application MUST be included in the published JAX-RS application. If either getClasses or getSingletons return a non-empty list then only those classes or singletons returned MUST be included in the published JAX-RS application. If not using the Servlet 3 framework pluggability mechanism (e.g. in a pre-Servet 3.0 container), the servlet-class or filterclass element of the web.xml descriptor SHOULD name the JAX-RS implementation-supplied servlet or filter class respectively. The Application subclass SHOULD be identified using an init-param with a param-name of javax.ws.rs.Application. Configuring JAX-RS services in container with Spring configuration file In web.xml one needs to register one or more CXFServlet(s) and link to an application context configuration. (1) Using Spring ContextLoaderListener the application context configuration is shared between all the CXFServlets.
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <context-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/beans.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>CXFServlet</servlet-name> <display-name>CXF Servlet</display-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping>

<servlet-name>CXFServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>

(2) Using CXFServlet init parameters each CXFServlet can get a unique application context configuration. Note, no Spring ContextLoaderListener is registered in web.xml in this case.
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>CXFServlet1</servlet-name> <display-name>CXF Servlet1</display-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <init-param> <param-name>config-location</param-name> <param-value>/WEB-INF/beans1.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>CXFServlet2</servlet-name> <display-name>CXF Servlet2</display-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <init-param> <param-name>config-location</param-name> <param-value>/WEB-INF/beans2.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet1</servlet-name> <url-pattern>/1/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>CXFServlet2</servlet-name> <url-pattern>/2/*</url-pattern>

</servlet-mapping> </web-app>

beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"> <!-- do not use import statements if CXFServlet init parameters link to this beans.xml --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <jaxrs:server id="customerService" address="/service1"> <jaxrs:serviceBeans> <ref bean="customerBean" /> </jaxrs:serviceBeans> </jaxrs:server> <bean id="customerBean" class="demo.jaxrs.server.CustomerService" /> </beans>

Configuring JAX-RS services using explicit bean configuration The jaxrs:server (and jaxrs:client) declarations depend on 'http://cxf.apache.org/jaxrs' Spring NamespaceHandler be available on classpath. If NamespaceHandler is missing then configure jaxrs endpoints using the CXF beans which actually handle the creation of jaxrs:server endpoints:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <bean class="org.apache.cxf.jaxrs.JAXRSServerFactoryBean" init-method="create">

<property name="address" value="/service1"/> <property:serviceBeans> <ref bean="customerBean" /> </property:serviceBeans> </bean> <bean id="customerBean" class="demo.jaxrs.server.CustomerService" /> </beans>

Spring AOP (To Do) http://cxf.apache.org/docs/jaxrs-services-configuration.html#JAXRSServicesConfiguration-SpringAOP

Você também pode gostar