You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Tom Davies <to...@atlassian.com> on 2007/11/08 02:03:02 UTC
Programmatically publishing a REST endpoint
Hi,
I have a SOAP services working fine, using the servlet transport. The
servlet is configured in web.xml, and the end point publishing happens
in the init method of the servlet (which is a subclass of CXFServlet:
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
Bus bus = this.getBus();
BusFactory.setDefaultBus(bus);
Endpoint.publish("/review",
SpringContext.getComponent("rpcReviewService"));
Endpoint e = Endpoint.create(HTTPBinding.HTTP_BINDING,
SpringContext.getComponent("restReviewService"));
e.publish("/rest");
Endpoint.publish("/auth",
SpringContext.getComponent("rpcAuthService"));
}
My RestReviewService class (based on the CustomerService example)
looks like:
@Component("restReviewService")
@WebService
@UriTemplate("/review/")
public class RestReviewService {
@Autowired
private ReviewService reviewService;
@HttpContext
UriInfo uriInfo;
@HttpMethod("GET")
@UriTemplate("/all/")
public List<ReviewData> getAllReviews() {
return reviewService.getAllReviews();
}
}
When I start my server the log says:
...
[java] Nov 8, 2007 11:34:53 AM
org.apache.cxf.service.factory.ReflectionServiceFactoryBean
buildServiceFromClass
[java] INFO: Creating Service {http://rpc.spi.crucible.atlassian.com/
}RestReviewServiceService from class
com.atlassian.crucible.spi.rpc.RestReviewService
[java] Nov 8, 2007 11:34:53 AM
org.apache.cxf.endpoint.ServerImpl initDestination
[java] INFO: Setting the server's publish address to be /rest
[java] Nov 8, 2007 11:34:53 AM
org.apache.cxf.service.factory.ReflectionServiceFactoryBean
buildServiceFromClass
...
But the service endpoint seems to be another SOAP service, as when I
go to http://localhost:6060/foo/services/rest/review/all I get:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/
envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</
faultcode><faultstring>No such operation: review</faultstring></
soap:Fault></soap:Body></soap:Envelope>
Thanks for any tips or pointers to documentation other than http://cwiki.apache.org/CXF20DOC/rest-with-jax-ws-provider-and-dispatch.html
I suspect I need to set the JAXRS binding for the endpoint, but I
don't know how to do it...
Tom
--
ATLASSIAN - http://www.atlassian.com
Our products help over 8,500 customers in more than 95 countries to
collaborate
RE: Programmatically publishing a REST endpoint
Posted by "Liu, Jervis" <jl...@iona.com>.
> -----Original Message-----
> From: Tom Davies [mailto:tom@atlassian.com]
> Sent: 2007?11?12? 6:23
> To: cxf-user@incubator.apache.org
> Subject: Re: Programmatically publishing a REST endpoint
>
>
>
> On 08/11/2007, at 7:37 PM, Liu, Jervis wrote:
>
> > Here you go, a brief document on how to build RESTful services in
> > CXF using JAX-RS (JSR-311):
> http://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+%28
JSR-311%29
> >
>
> Hi Jervis,
>
> Thanks for the information.
>
> One clarification: as I'm using the servlet transport, I
> don't want to
> set an explicit address, just a path component, so that the REST API
> is under the URL my CXFServlet maps to.
>
> So given that I have this code to publish my SOAP services:
>
> public void init(ServletConfig servletConfig) throws
> ServletException {
> super.init(servletConfig);
> Bus bus = this.getBus();
> BusFactory.setDefaultBus(bus);
> Endpoint.publish("/review",
> SpringContext.getComponent("rpcReviewService"));
> Endpoint.publish("/auth",
> SpringContext.getComponent("rpcAuthService"));
> ... REST publishing goes here ...
> }
>
> Can I use something like:
> JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
> sf.setResourceClasses(RestReviewService.class);
> //default lifecycle is per-request, change it to singleton
> sf.setResourceProvider(RestReviewService.class, new
> SingletonResourceProvider());
> sf.setBus(bus);
> sf.setAddress("/rest"); // will this work?
>
> sf.create();
>
This should work. Willem Jiang had done some work on this part recently to make it possible to publish an endpoint using servlet transport both from spring configuration and API.
> A more general question: What are the pros and cons of using
> CXF HTTP
> binding vs. JSR-311 for REST?
>
If you take a closer look into JSR-311 and CXF HTTP binding, you may find that they have a lot of things in common, such as the URITemplate, HTTP Method annotation etc. Maybe the annotation names are different, but the basic ideas are same. So I would say you can view JSR-311 as an evolved and more standard version of CXF HTTP binding.
> Thanks again,
> Tom
>
> --
> ATLASSIAN - http://www.atlassian.com
> Our products help over 8,500 customers in more than 95 countries to
> collaborate
>
>
>
>
>
----------------------------
IONA Technologies PLC (registered in Ireland)
Registered Number: 171387
Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland
Re: Programmatically publishing a REST endpoint
Posted by Tom Davies <to...@atlassian.com>.
On 08/11/2007, at 7:37 PM, Liu, Jervis wrote:
> Here you go, a brief document on how to build RESTful services in
> CXF using JAX-RS (JSR-311): http://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+%28JSR-311%29
>
Hi Jervis,
Thanks for the information.
One clarification: as I'm using the servlet transport, I don't want to
set an explicit address, just a path component, so that the REST API
is under the URL my CXFServlet maps to.
So given that I have this code to publish my SOAP services:
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
Bus bus = this.getBus();
BusFactory.setDefaultBus(bus);
Endpoint.publish("/review",
SpringContext.getComponent("rpcReviewService"));
Endpoint.publish("/auth",
SpringContext.getComponent("rpcAuthService"));
... REST publishing goes here ...
}
Can I use something like:
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(RestReviewService.class);
//default lifecycle is per-request, change it to singleton
sf.setResourceProvider(RestReviewService.class, new
SingletonResourceProvider());
sf.setBus(bus);
sf.setAddress("/rest"); // will this work?
sf.create();
A more general question: What are the pros and cons of using CXF HTTP
binding vs. JSR-311 for REST?
Thanks again,
Tom
--
ATLASSIAN - http://www.atlassian.com
Our products help over 8,500 customers in more than 95 countries to
collaborate
RE: Programmatically publishing a REST endpoint
Posted by "Liu, Jervis" <jl...@iona.com>.
Here you go, a brief document on how to build RESTful services in CXF using JAX-RS (JSR-311): http://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+%28JSR-311%29
BTW, at the moment we do not support the return of a List in JAX-RS (e.g., List<ReviewData> getAllReviews() ), I am even not sure whether or not this should be supported. The main problem is a direct mapping from List to XML would result in an invalid XML as it has multiple root elements, thus can not be displayed on browsers. You will need a wrapper object, i.e., ReviewDataList getAllReviews(), where ReviewDataList is defined as:
@XmlRootElement(name = "ReviewDataList")
public class ReviewDataList {
private Collection<ReviewData> rds;
public Collection<ReviewData> getReviewData() {
return rds;
}
public void setReviewData(Collection<ReviewData> r) {
this.rds= r;
}
}
Jervis
> -----Original Message-----
> From: Liu, Jervis [mailto:jliu@iona.com]
> Sent: 2007?11?8? 15:06
> To: cxf-user@incubator.apache.org
> Subject: RE: Programmatically publishing a REST endpoint
>
>
> Currently there are three ways to build a RESTful service in
> CXF. [1] and [2] should give you enough information on how to
> use CXF HTTP binding and JAX-WS Dispatch/Provider to build a
> RESTful service. Now we have a third option - using JSR-311.
> You are very welcome to try this new feature out, any
> feedbacks would be hightly appreciated. This has not been
> documented yet, but I will do this soon. At the same time,
> there are couple of examples under system test directory [3],
> which hopefully will help you out.
>
> To answer your specific question, if you want to use CXF HTTP
> binding, you need to write your server mainline as below:
>
> JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
> sf.setServiceClass(PeopleService.class);
> sf.getServiceFactory().setWrapped(true);
> sf.setBindingId(HttpBindingFactory.HTTP_BINDING_ID);
> sf.setAddress("http://localhost:9001/");
>
> PeopleService peopleService = new PeopleServiceImpl();
> sf.getServiceFactory().setInvoker(new BeanInvoker(peopleService));
>
> Server svr = sf.create();
>
> Your RestReviewService.class suggests that you are actually
> using JSR-311, in this case, your server main line is as below:
>
> JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
> sf.setResourceClasses(RestReviewService.class);
> //default lifecycle is per-request, change it to singleton
> sf.setResourceProvider(RestReviewService.class, new
> SingletonResourceProvider());
> sf.setAddress("http://localhost:9001/");
>
> sf.create();
>
>
> [1]. http://cwiki.apache.org/CXF20DOC/http-binding.html
> [2].
> http://cwiki.apache.org/CXF20DOC/rest-with-jax-ws-provider-and
> -dispatch.html
> [3].
> https://svn.apache.org/repos/asf/incubator/cxf/trunk/systests/
> src/test/java/org/apache/cxf/systest/jaxrs
>
> Hope this helps,
> Jervis
>
>
>
> > -----Original Message-----
> > From: Tom Davies [mailto:tom@atlassian.com]
> > Sent: 2007?11?8? 9:03
> > To: cxf-user@incubator.apache.org
> > Subject: Programmatically publishing a REST endpoint
> >
> >
> > Hi,
> >
> > I have a SOAP services working fine, using the servlet
> > transport. The
> > servlet is configured in web.xml, and the end point
> > publishing happens
> > in the init method of the servlet (which is a subclass of
> CXFServlet:
> >
> > public void init(ServletConfig servletConfig) throws
> > ServletException {
> > super.init(servletConfig);
> > Bus bus = this.getBus();
> > BusFactory.setDefaultBus(bus);
> > Endpoint.publish("/review",
> > SpringContext.getComponent("rpcReviewService"));
> > Endpoint e = Endpoint.create(HTTPBinding.HTTP_BINDING,
> > SpringContext.getComponent("restReviewService"));
> > e.publish("/rest");
> > Endpoint.publish("/auth",
> > SpringContext.getComponent("rpcAuthService"));
> > }
> >
> > My RestReviewService class (based on the CustomerService example)
> > looks like:
> >
> > @Component("restReviewService")
> > @WebService
> > @UriTemplate("/review/")
> > public class RestReviewService {
> > @Autowired
> > private ReviewService reviewService;
> >
> > @HttpContext
> > UriInfo uriInfo;
> >
> > @HttpMethod("GET")
> > @UriTemplate("/all/")
> > public List<ReviewData> getAllReviews() {
> > return reviewService.getAllReviews();
> > }
> > }
> >
> > When I start my server the log says:
> > ...
> > [java] Nov 8, 2007 11:34:53 AM
> > org.apache.cxf.service.factory.ReflectionServiceFactoryBean
> > buildServiceFromClass
> > [java] INFO: Creating Service
> > {http://rpc.spi.crucible.atlassian.com/
> > }RestReviewServiceService from class
> > com.atlassian.crucible.spi.rpc.RestReviewService
> > [java] Nov 8, 2007 11:34:53 AM
> > org.apache.cxf.endpoint.ServerImpl initDestination
> > [java] INFO: Setting the server's publish address to be /rest
> > [java] Nov 8, 2007 11:34:53 AM
> > org.apache.cxf.service.factory.ReflectionServiceFactoryBean
> > buildServiceFromClass
> > ...
> >
> > But the service endpoint seems to be another SOAP service,
> as when I
> > go to http://localhost:6060/foo/services/rest/review/all I get:
> >
> > <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/
> > envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</
> > faultcode><faultstring>No such operation: review</faultstring></
> > soap:Fault></soap:Body></soap:Envelope>
> >
> > Thanks for any tips or pointers to documentation other than
> > http://cwiki.apache.org/CXF20DOC/rest-with-jax-ws-provider-and
> > -dispatch.html
> >
> > I suspect I need to set the JAXRS binding for the endpoint, but I
> > don't know how to do it...
> >
> > Tom
> >
> > --
> > ATLASSIAN - http://www.atlassian.com
> > Our products help over 8,500 customers in more than 95
> countries to
> > collaborate
> >
> >
> >
> >
> >
>
> ----------------------------
> IONA Technologies PLC (registered in Ireland)
> Registered Number: 171387
> Registered Address: The IONA Building, Shelbourne Road,
> Dublin 4, Ireland
>
----------------------------
IONA Technologies PLC (registered in Ireland)
Registered Number: 171387
Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland
RE: Programmatically publishing a REST endpoint
Posted by "Liu, Jervis" <jl...@iona.com>.
Currently there are three ways to build a RESTful service in CXF. [1] and [2] should give you enough information on how to use CXF HTTP binding and JAX-WS Dispatch/Provider to build a RESTful service. Now we have a third option - using JSR-311. You are very welcome to try this new feature out, any feedbacks would be hightly appreciated. This has not been documented yet, but I will do this soon. At the same time, there are couple of examples under system test directory [3], which hopefully will help you out.
To answer your specific question, if you want to use CXF HTTP binding, you need to write your server mainline as below:
JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
sf.setServiceClass(PeopleService.class);
sf.getServiceFactory().setWrapped(true);
sf.setBindingId(HttpBindingFactory.HTTP_BINDING_ID);
sf.setAddress("http://localhost:9001/");
PeopleService peopleService = new PeopleServiceImpl();
sf.getServiceFactory().setInvoker(new BeanInvoker(peopleService));
Server svr = sf.create();
Your RestReviewService.class suggests that you are actually using JSR-311, in this case, your server main line is as below:
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(RestReviewService.class);
//default lifecycle is per-request, change it to singleton
sf.setResourceProvider(RestReviewService.class, new SingletonResourceProvider());
sf.setAddress("http://localhost:9001/");
sf.create();
[1]. http://cwiki.apache.org/CXF20DOC/http-binding.html
[2]. http://cwiki.apache.org/CXF20DOC/rest-with-jax-ws-provider-and-dispatch.html
[3]. https://svn.apache.org/repos/asf/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs
Hope this helps,
Jervis
> -----Original Message-----
> From: Tom Davies [mailto:tom@atlassian.com]
> Sent: 2007?11?8? 9:03
> To: cxf-user@incubator.apache.org
> Subject: Programmatically publishing a REST endpoint
>
>
> Hi,
>
> I have a SOAP services working fine, using the servlet
> transport. The
> servlet is configured in web.xml, and the end point
> publishing happens
> in the init method of the servlet (which is a subclass of CXFServlet:
>
> public void init(ServletConfig servletConfig) throws
> ServletException {
> super.init(servletConfig);
> Bus bus = this.getBus();
> BusFactory.setDefaultBus(bus);
> Endpoint.publish("/review",
> SpringContext.getComponent("rpcReviewService"));
> Endpoint e = Endpoint.create(HTTPBinding.HTTP_BINDING,
> SpringContext.getComponent("restReviewService"));
> e.publish("/rest");
> Endpoint.publish("/auth",
> SpringContext.getComponent("rpcAuthService"));
> }
>
> My RestReviewService class (based on the CustomerService example)
> looks like:
>
> @Component("restReviewService")
> @WebService
> @UriTemplate("/review/")
> public class RestReviewService {
> @Autowired
> private ReviewService reviewService;
>
> @HttpContext
> UriInfo uriInfo;
>
> @HttpMethod("GET")
> @UriTemplate("/all/")
> public List<ReviewData> getAllReviews() {
> return reviewService.getAllReviews();
> }
> }
>
> When I start my server the log says:
> ...
> [java] Nov 8, 2007 11:34:53 AM
> org.apache.cxf.service.factory.ReflectionServiceFactoryBean
> buildServiceFromClass
> [java] INFO: Creating Service
> {http://rpc.spi.crucible.atlassian.com/
> }RestReviewServiceService from class
> com.atlassian.crucible.spi.rpc.RestReviewService
> [java] Nov 8, 2007 11:34:53 AM
> org.apache.cxf.endpoint.ServerImpl initDestination
> [java] INFO: Setting the server's publish address to be /rest
> [java] Nov 8, 2007 11:34:53 AM
> org.apache.cxf.service.factory.ReflectionServiceFactoryBean
> buildServiceFromClass
> ...
>
> But the service endpoint seems to be another SOAP service, as when I
> go to http://localhost:6060/foo/services/rest/review/all I get:
>
> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/
> envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</
> faultcode><faultstring>No such operation: review</faultstring></
> soap:Fault></soap:Body></soap:Envelope>
>
> Thanks for any tips or pointers to documentation other than
> http://cwiki.apache.org/CXF20DOC/rest-with-jax-ws-provider-and
> -dispatch.html
>
> I suspect I need to set the JAXRS binding for the endpoint, but I
> don't know how to do it...
>
> Tom
>
> --
> ATLASSIAN - http://www.atlassian.com
> Our products help over 8,500 customers in more than 95 countries to
> collaborate
>
>
>
>
>
----------------------------
IONA Technologies PLC (registered in Ireland)
Registered Number: 171387
Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland