zoukankan      html  css  js  c++  java
  • Apache CXF 3.0: CDI 1.1 Support as Alternative to Spring--reference

    With Apache CXF 3.0 just being released a couple of weeks ago, the project makes yet another important step to fulfill the JAX-RS 2.0 specification requirements: integration with CDI 1.1. In this blog post we are going to look on a couple of examples of how Apache CXF 3.0 and Apache CXF 3.0 work together.

    Starting from version 3.0Apache CXF includes a new module, named cxf-integration-cdi which could be added easily to your Apache Maven POM file:

    1.<dependency>
    2.<groupId>org.apache.cxf</groupId>
    3.<artifactId>cxf-integration-cdi</artifactId>
    4.<version>3.0.0</version>
    5.</dependency>

    This new module brings just two components (in fact, a bit more but those are the key ones):

    • CXFCdiServlet: the servlet to bootstrap Apache CXF application, serving the same purpose asCXFServlet and CXFNonSpringJaxrsServlet, ...
    • JAXRSCdiResourceExtension: portable CDI 1.1 extension where all the magic happens

    When run in CDI 1.1-enabled environment, the portable extensions are discovered by CDI 1.1 container and initialized using life-cycle events. And that is literally all what you need! Let us see the real application in action.

    We are going to build a very simple JAX-RS 2.0 application to manage people using Apache CXF 3.0 andJBoss Weld 2.1, the CDI 1.1 reference implementation. The Person class we are going to use for a person representation is just a simple Java bean:

    01.package com.example.model;
    02. 
    03.public class Person{
    04.private String email;
    05.private String firstName;
    06.private String lastName;
    07.public Person(){
    08.}
    09.public Person(final String email, final String firstName, final StringlastName){
    10.this.email = email;
    11.this.firstName = firstName;
    12.this.lastName = lastName;
    13.}
    14.//getters and setters are ommited
    15.//...

    As it is quite common now, we are going to run our application inside embedded Jetty 9.1 container and ourStarter class does exactly that:

    01.package com.example;
    02. 
    03.import org.apache.cxf.cdi.CXFCdiServlet;
    04.import org.eclipse.jetty.server.Server;
    05.import org.eclipse.jetty.servlet.ServletContextHandler;
    06.import org.eclipse.jetty.servlet.ServletHolder;
    07.importorg.jboss.weld.environment.servlet.BeanManagerResourceBindingListener;
    08.import org.jboss.weld.environment.servlet.Listener;
    09. 
    10.public class Starter {
    11.public static void main( final String[] args ) throws Exception {
    12.final Server server = new Server( 8080 );
    13. 
    14.// Register and map the dispatcher servlet
    15.final ServletHolder servletHolder = new ServletHolder( newCXFCdiServlet() );
    16.final ServletContextHandler context = new ServletContextHandler();  
    17.context.setContextPath( "/" );   
    18.context.addEventListener( new Listener() );  
    19.context.addEventListener( new BeanManagerResourceBindingListener() );
    20.context.addServlet( servletHolder, "/rest/*" );
    21. 
    22.server.setHandler( context );
    23.server.start();       
    24.server.join();
    25.}
    26.}

    Please notice the presence of CXFCdiServlet and two mandatory listeners which were added to the context:

    • org.jboss.weld.environment.servlet.Listener is responsible for CDI injections
    • org.jboss.weld.environment.servlet.BeanManagerResourceBindingListener binds the reference to the BeanManager to JNDI location java:comp/env/BeanManager to make it accessible anywhere from the application

    With that, the full power of CDI 1.1 is at your disposal. Let us introduce the PeopleService class annotated with @Named annotation and with an initialization method declared and annotated with @PostConstruct just to create one person.

    01.@Named
    02.public class PeopleService {
    03.private final ConcurrentMap< String, Person > persons =
    04.new ConcurrentHashMap< String, Person >();
    05. 
    06.@PostConstruct
    07.public void init() { 
    08.persons.put( "a@b.com", new Person( "a@b.com", "Tom", "Bombadilt" ) );
    09.}
    10. 
    11.// Additional methods
    12.// ...
    13.}

    Up to now we have said nothing about configuring JAX-RS 2.0 applications and resources in CDI 1.1enviroment. The reason for that is very simple: depending on the application, you may go with zero-effort configuration or fully customizable one. Let us go through both approaches.

    With zero-effort configuration, you may define an empty JAX-RS 2.0 application and any number of JAX-RS 2.0 resources: Apache CXF 3.0 implicitly will wire them together by associating each resource class with this application. Here is an example of JAX-RS 2.0 application:

    1.package com.example.rs;
    2.import javax.ws.rs.ApplicationPath;
    3.import javax.ws.rs.core.Application;
    4. 
    5.@ApplicationPath( "api" )
    6.public class JaxRsApiApplication extends Application {
    7.}

    And here is a JAX-RS 2.0 resource PeopleRestService which injects the PeopleService managed bean:

    01.package com.example.rs;
    02. 
    03.import java.util.Collection;
    04. 
    05.import javax.inject.Inject;
    06.import javax.ws.rs.DELETE;
    07.import javax.ws.rs.DefaultValue;
    08.import javax.ws.rs.FormParam;
    09.import javax.ws.rs.GET;
    10.import javax.ws.rs.POST;
    11.import javax.ws.rs.PUT;
    12.import javax.ws.rs.Path;
    13.import javax.ws.rs.PathParam;
    14.import javax.ws.rs.Produces;
    15.import javax.ws.rs.QueryParam;
    16.import javax.ws.rs.core.Context;
    17.import javax.ws.rs.core.MediaType;
    18.import javax.ws.rs.core.Response;
    19.import javax.ws.rs.core.UriInfo;
    20. 
    21.import com.example.model.Person;
    22.import com.example.services.PeopleService;
    23. 
    24.@Path( "/people" )
    25.public class PeopleRestService {
    26.@Inject private PeopleService peopleService;
    27. 
    28.@Produces( { MediaType.APPLICATION_JSON } )
    29.@GET
    30.public Collection< Person > getPeople( @QueryParam( "page")@DefaultValue( "1" ) final int page ) {
    31.// ...
    32.}
    33. 
    34.@Produces( { MediaType.APPLICATION_JSON } )
    35.@Path( "/{email}" )
    36.@GET
    37.public Person getPerson( @PathParam( "email" ) final String email ) {
    38.// ...
    39.}
    40. 
    41.@Produces( { MediaType.APPLICATION_JSON  } )
    42.@POST
    43.public Response addPerson( @Context final UriInfo uriInfo,
    44.@FormParam( "email" ) final String email,
    45.@FormParam( "firstName" ) final String firstName,
    46.@FormParam( "lastName" ) final String lastName ) {
    47.// ...
    48.}
    49. 
    50.// More HTTP methods here
    51.// ...
    52.}

    Nothing else is required: Apache CXF 3.0 application could be run like that and be fully functional. The complete source code of the sample project is available on GitHub. Please keep in mind that if you are following this style, only single empty JAX-RS 2.0 application should be declared.

    With customizable approach more options are available but a bit more work have to be done. Each JAX-RS 2.0 application should provide non-empty getClasses() or/and getSingletons() collections implementation. However, JAX-RS 2.0 resource classes stay unchanged. Here is an example (which basically leads to the same application configuration we have seen before):

    01.package com.example.rs;
    02. 
    03.import java.util.Arrays;
    04.import java.util.HashSet;
    05.import java.util.Set;
    06. 
    07.import javax.enterprise.inject.Produces;
    08.import javax.inject.Inject;
    09.import javax.ws.rs.ApplicationPath;
    10.import javax.ws.rs.core.Application;
    11. 
    12.import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
    13. 
    14.@ApplicationPath( "api" )
    15.public class JaxRsApiApplication extends Application {
    16.@Inject private PeopleRestService peopleRestService;
    17.@Produces private JacksonJsonProvider jacksonJsonProvider = newJacksonJsonProvider(); 
    18. 
    19.@Override
    20.public Set< Object > getSingletons() {
    21.return new HashSet<>(
    22.Arrays.asList(
    23.peopleRestService,
    24.jacksonJsonProvider
    25.)
    26.);
    27.}
    28.}

    Please notice, that JAXRSCdiResourceExtension portable CDI 1.1 extension automatically creates managed beans for each JAX-RS 2.0 applications (the ones extending Application) and resources (annotated with@Path). As such, those are immediately available for injection (as for example PeopleRestService in the snippet above). The class JacksonJsonProvider is annotated with @Provider annotation and as such will be treated as JAX-RS 2.0 provider. There are no limit on JAX-RS 2.0 applications which could be defined in this way. The complete source code of the sample project using this appoarch is available on GitHub

    No matter which approach you have chosen, our sample application is going to work the same. Let us build it and run:

    1.&gt; mvn clean package
    2.&gt; java -jar target/jax-rs-2.0-cdi-0.0.1-SNAPSHOT.jar

    Calling the couple of implemented REST APIs confirms that application is functioning and configured properly. Let us issue the GET command to ensure that the method of PeopleService annotated with @PostConstructhas been called upon managed bean creation.

    01.&gt; curl http://localhost:8080/rest/api/people
    02. 
    03.HTTP/1.1 200 OK
    04.Content-Type: application/json
    05.Date: Thu, 29 May 2014 22:39:35 GMT
    06.Transfer-Encoding: chunked
    07.Server: Jetty(9.1.z-SNAPSHOT)
    08. 
    09.[{"email":"a@b.com","firstName":"Tom","lastName":"Bombadilt"}]

    And here is the example of POST command:

    01.&gt; curl -i http://localhost:8080/rest/api/people -X POST -d"email=a@c.com&firstName=Tom&lastName=Knocker"
    02. 
    03.HTTP/1.1 201 Created
    04.Content-Type: application/json
    05.Date: Thu, 29 May 2014 22:40:08 GMT
    06.Location: http://localhost:8080/rest/api/people/a@c.com
    07.Transfer-Encoding: chunked
    08.Server: Jetty(9.1.z-SNAPSHOT)
    09. 
    10.{"email":"a@c.com","firstName":"Tom","lastName":"Knocker"}

    In this blog post we have just scratched the surface of what is possible now with Apache CXF and CDI 1.1integration. Just to mention that embedded Apache Tomcat 7.x / 8.x as well as WAR-based deployments ofApache CXF with CDI 1.1 are possible on most JEE application servers and servlet containers.

    Please take a look on official documentation and give it a try!

    The complete source code is available on GitHub.

    reference :http://java.dzone.com/articles/apache-cxf-30-cdi-11-support

  • 相关阅读:
    win7下 iis配置 不能添加默认文档的 解决方案
    经典SQL语句大全
    Sql 行转列问题总结
    jQuery获取Select选择的Text和 Value(转)
    如何让虚拟目录里面的webconfig不继承网站的设置
    SQL2008 用户'sa'登录失败(错误18456)图文解决方法
    ASP.NET实现公历转农历的简单方法
    你的DNN站点慢了么?
    SQLServer2005删除log文件和清空日志的方案
    由于未能创建 Microsoft Visual C# 2008 编译器,因此未能打开项目 "xxx"
  • 原文地址:https://www.cnblogs.com/davidwang456/p/3765214.html
Copyright © 2011-2022 走看看