You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Voß, Marko <Ma...@fiz-Karlsruhe.de> on 2012/04/02 14:34:21 UTC

Easy and quick access to existing JAX-RS interface endpoints

Hello,

I need to know the existing endpoints of a JAX-RS interface.

I did the following solution first:

List<ClassResourceInfo> resources = jaxrsServerFactoryBean.getServiceFactory().getClassResourceInfo();
for (ClassResourceInfo resource : resources) {
     if (FooRestService.class.isAssignableFrom(resource.getServiceClass())) {
         LOG.warn("Foo REST-Service locally available!");
         LOG.warn("Service path: " + resource.getPath().value());
         for (OperationResourceInfo ori : resource.getMethodDispatcher().getOperationResourceInfos()) {
             if (ori.getAnnotatedMethod().getName().equals("retrieve")) {
                 LOG.warn("Method path: " + ori.getAnnotatedMethod().getAnnotation(Path.class).value());
             }
         }
     }
}

Output:

Foo REST-Service locally available!
Service path: /foo/something
Method path: /{id}


This solution however may not work, when dealing with distributed services. One server instance may not have all 
services registered to its jaxrs:server bean configured in Spring.

What we do have available on all instances are the JAX-RS interfaces because of we need to perform requests to the other 
instances of course.

So, is there an easy way to get all the endpoints or do I have to implement the reflection on my own?

I do know, that CXF is already handling this in some classes. I tried the following, which does not work, because the 
iteration has no items to iterate through. I would prefer to reuse the existing code in CXF for this.

JAXRSServiceFactoryBean serviceFactoryBean = new JAXRSServiceFactoryBean();
serviceFactoryBean.setResourceClass(FooRestServiceImpl.class);
Service service = serviceFactoryBean.create();
for (Endpoint endpoint : service.getEndpoints().values()) {
     LOG.warn("Endpoints: " + endpoint.getEndpointInfo());
}

Output:

<nothing>



Thank you in advance and best regards,

Marko


-------------------------------------------------------

Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH. 
Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892. 
Geschäftsführerin: Sabine Brünger-Weilandt. 
Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.



Re: Easy and quick access to existing JAX-RS interface endpoints

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Marko, I see, got confused a bit by the reference to UriBuilder :-), 
indeed UriInfo can only help with capturing the information relevant to 
the current root resource handler, and even then it can be tricky to get 
to the path ending at the root resource...

Cheers, Sergey
On 02/04/12 18:00, Voß, Marko wrote:
> Hello Sergey,
>
>   >  So UriInfo won't help in your case ?
>
> I am not quite sure about this. Let me give you a more detailed example:
>
> Service Foo:
> ------------
>
> @Path("/foo")
> public interface Foo {
>
>     @Path("/{id}")
>     Foo retrieve(@PathParam("id") final String id);
> }
>
> Service Bar:
> ------------
>
> @Path("/bar")
> public interface Bar {
>
>     @Path("/{id}")
>     Bar retrieve(@PathParam("id") final String id);
> }
>
> Simple installation:
> --------------------
>
> The jaxrs:server will look like this:
>
> <jaxrs:server id="RestServices" address="">
>     <jaxrs:serviceBeans>
>       <!-- Configured services available on runtime -->
>       <ref bean="service.foo"/>
>       <ref bean="service.bar"/>
>     </jaxrs:serviceBeans>
> </jaxrs:server>
>
> Distributed services installation:
> ----------------------------------
>
> The jaxrs:server configurations will look like this:
>
> Machine A (Service Foo):
> ------------------------
>
> <jaxrs:server id="RestServices" address="">
>     <jaxrs:serviceBeans>
>       <!-- Configured services available on runtime -->
>       <ref bean="service.foo"/>
>     </jaxrs:serviceBeans>
> </jaxrs:server>
>
> Machine B (Service Bar):
> ------------------------
>
> <jaxrs:server id="RestServices" address="">
>     <jaxrs:serviceBeans>
>       <!-- Configured services available on runtime -->
>       <ref bean="service.bar"/>
>     </jaxrs:serviceBeans>
> </jaxrs:server>
>
> So I guess the injected UriInfo on service Foo is unable to get any information about service Bar and vice versa.
>
>
> Best regards,
>
> Marko
>
>
> -------------------------------------------------------
>
> Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH.
> Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892.
> Geschäftsführerin: Sabine Brünger-Weilandt.
> Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.
>
>


Re: Easy and quick access to existing JAX-RS interface endpoints

Posted by Voß, Marko <Ma...@fiz-Karlsruhe.de>.
Hello Sergey,

 > So UriInfo won't help in your case ?

I am not quite sure about this. Let me give you a more detailed example:

Service Foo:
------------

@Path("/foo")
public interface Foo {

   @Path("/{id}")
   Foo retrieve(@PathParam("id") final String id);
}

Service Bar:
------------

@Path("/bar")
public interface Bar {

   @Path("/{id}")
   Bar retrieve(@PathParam("id") final String id);
}

Simple installation:
--------------------

The jaxrs:server will look like this:

<jaxrs:server id="RestServices" address="">
   <jaxrs:serviceBeans>
     <!-- Configured services available on runtime -->
     <ref bean="service.foo"/>
     <ref bean="service.bar"/>
   </jaxrs:serviceBeans>
</jaxrs:server>

Distributed services installation:
----------------------------------

The jaxrs:server configurations will look like this:

Machine A (Service Foo):
------------------------

<jaxrs:server id="RestServices" address="">
   <jaxrs:serviceBeans>
     <!-- Configured services available on runtime -->
     <ref bean="service.foo"/>
   </jaxrs:serviceBeans>
</jaxrs:server>

Machine B (Service Bar):
------------------------

<jaxrs:server id="RestServices" address="">
   <jaxrs:serviceBeans>
     <!-- Configured services available on runtime -->
     <ref bean="service.bar"/>
   </jaxrs:serviceBeans>
</jaxrs:server>

So I guess the injected UriInfo on service Foo is unable to get any information about service Bar and vice versa.


Best regards,

Marko


-------------------------------------------------------

Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH. 
Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892. 
Geschäftsführerin: Sabine Brünger-Weilandt. 
Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.



Re: Easy and quick access to existing JAX-RS interface endpoints

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Marko
On 02/04/12 17:19, Voß, Marko wrote:
> Hello Sergey,
>
> thanks again!
>
welcome
> I figured out I could simply use the UriBuilder for this:
>
> UriBuilder uriBuilder = UriBuilder.fromResource(MyJaxRsInterface.class);
> URI uri = uriBuilder.path(MyJaxRsInterface.class, "retrieve").build("foo-id");
> LOG.warn("PATH: " + jaxrsServerFactoryBean.getAddress() + '/' + uri.toString());
>
> When distributing services in a cluster for example, we expect the jaxrs:server address to be equal on all machines.
>
> So this should do the trick too. Especially, when MyJaxRsInterface-service is not available on the server, which
> requires to know the endpoints to put them into the delivered resources for example. :)
So UriInfo won't help in your case ?

Cheers, Sergey
>
>
> Best regards,
>
> Marko
>
> Am 02.04.2012 15:53, schrieb Sergey Beryozkin:
>> Hi Marko
>> On 02/04/12 15:34, Voß, Marko wrote:
>>> Hello,
>>>
>>> I need to know the existing endpoints of a JAX-RS interface.
>>>
>>
>> The services page should return the list of all the REST (&  WS) endpoints available and then individual WADL instances
>> will describe all the root resources which constitute a given endpoint,
>>
>>> I did the following solution first:
>>>
>>> List<ClassResourceInfo>  resources = jaxrsServerFactoryBean.getServiceFactory().getClassResourceInfo();
>>> for (ClassResourceInfo resource : resources) {
>>> if (FooRestService.class.isAssignableFrom(resource.getServiceClass())) {
>>> LOG.warn("Foo REST-Service locally available!");
>>> LOG.warn("Service path: " + resource.getPath().value());
>>> for (OperationResourceInfo ori : resource.getMethodDispatcher().getOperationResourceInfos()) {
>>> if (ori.getAnnotatedMethod().getName().equals("retrieve")) {
>>> LOG.warn("Method path: " + ori.getAnnotatedMethod().getAnnotation(Path.class).value());
>>> }
>>> }
>>> }
>>> }
>>>
>>> Output:
>>>
>>> Foo REST-Service locally available!
>>> Service path: /foo/something
>>> Method path: /{id}
>>>
>>>
>>> This solution however may not work, when dealing with distributed services. One server instance may not have all
>>> services registered to its jaxrs:server bean configured in Spring.
>>>
>>> What we do have available on all instances are the JAX-RS interfaces because of we need to perform requests to the other
>>> instances of course.
>>>
>>> So, is there an easy way to get all the endpoints or do I have to implement the reflection on my own?
>>>
>>> I do know, that CXF is already handling this in some classes. I tried the following, which does not work, because the
>>> iteration has no items to iterate through. I would prefer to reuse the existing code in CXF for this.
>>>
>>> JAXRSServiceFactoryBean serviceFactoryBean = new JAXRSServiceFactoryBean();
>>> serviceFactoryBean.setResourceClass(FooRestServiceImpl.class);
>>> Service service = serviceFactoryBean.create();
>>> for (Endpoint endpoint : service.getEndpoints().values()) {
>>> LOG.warn("Endpoints: " + endpoint.getEndpointInfo());
>>> }
>>>
>>> Output:
>>>
>>> <nothing>
>> Right now the model representing JAX-RS endpoints and the CXF model which is optimized for representing WS service and
>> endpoints are not closely related, there's a link but it's not a 1 to 1 match,
>> the following will only give you the list of all the root resource for a current endpoint.
>>
>> Service service = serverFactoryBean.getServiceFactory().getService();
>> List<ClassResourceInfo>  list = ((JAXRSServiceImpl)service).getClassResourceInfos();
>>
>> They can also be retrieved at runtime from the current message:
>>
>> Service service = message.getExchange().get(Service.class);
>> List<ClassResourceInfo>  resources = ((JAXRSServiceImpl)service).getClassResourceInfos();
>>
>> In order to get the list if all the jaxrs endpoints you'd need to get
>> a DestinationRegistryManager extension from the bus and enumerate over all the destinations and those which return
>> null for getEndpointInfo().getInterface() do represent restful endpoints :-) so if possible try the services page for
>> the latter task :-)
>>
>> Sergey
>>
>>
>>>
>
>



Re: Easy and quick access to existing JAX-RS interface endpoints

Posted by Voß, Marko <Ma...@fiz-Karlsruhe.de>.
Hello Sergey,

thanks again!

I figured out I could simply use the UriBuilder for this:

UriBuilder uriBuilder = UriBuilder.fromResource(MyJaxRsInterface.class);
URI uri = uriBuilder.path(MyJaxRsInterface.class, "retrieve").build("foo-id");
LOG.warn("PATH: " + jaxrsServerFactoryBean.getAddress() + '/' + uri.toString());

When distributing services in a cluster for example, we expect the jaxrs:server address to be equal on all machines.

So this should do the trick too. Especially, when MyJaxRsInterface-service is not available on the server, which 
requires to know the endpoints to put them into the delivered resources for example. :)


Best regards,

Marko

Am 02.04.2012 15:53, schrieb Sergey Beryozkin:
> Hi Marko
> On 02/04/12 15:34, Voß, Marko wrote:
>> Hello,
>>
>> I need to know the existing endpoints of a JAX-RS interface.
>>
>
> The services page should return the list of all the REST (& WS) endpoints available and then individual WADL instances
> will describe all the root resources which constitute a given endpoint,
>
>> I did the following solution first:
>>
>> List<ClassResourceInfo> resources = jaxrsServerFactoryBean.getServiceFactory().getClassResourceInfo();
>> for (ClassResourceInfo resource : resources) {
>> if (FooRestService.class.isAssignableFrom(resource.getServiceClass())) {
>> LOG.warn("Foo REST-Service locally available!");
>> LOG.warn("Service path: " + resource.getPath().value());
>> for (OperationResourceInfo ori : resource.getMethodDispatcher().getOperationResourceInfos()) {
>> if (ori.getAnnotatedMethod().getName().equals("retrieve")) {
>> LOG.warn("Method path: " + ori.getAnnotatedMethod().getAnnotation(Path.class).value());
>> }
>> }
>> }
>> }
>>
>> Output:
>>
>> Foo REST-Service locally available!
>> Service path: /foo/something
>> Method path: /{id}
>>
>>
>> This solution however may not work, when dealing with distributed services. One server instance may not have all
>> services registered to its jaxrs:server bean configured in Spring.
>>
>> What we do have available on all instances are the JAX-RS interfaces because of we need to perform requests to the other
>> instances of course.
>>
>> So, is there an easy way to get all the endpoints or do I have to implement the reflection on my own?
>>
>> I do know, that CXF is already handling this in some classes. I tried the following, which does not work, because the
>> iteration has no items to iterate through. I would prefer to reuse the existing code in CXF for this.
>>
>> JAXRSServiceFactoryBean serviceFactoryBean = new JAXRSServiceFactoryBean();
>> serviceFactoryBean.setResourceClass(FooRestServiceImpl.class);
>> Service service = serviceFactoryBean.create();
>> for (Endpoint endpoint : service.getEndpoints().values()) {
>> LOG.warn("Endpoints: " + endpoint.getEndpointInfo());
>> }
>>
>> Output:
>>
>> <nothing>
> Right now the model representing JAX-RS endpoints and the CXF model which is optimized for representing WS service and
> endpoints are not closely related, there's a link but it's not a 1 to 1 match,
> the following will only give you the list of all the root resource for a current endpoint.
>
> Service service = serverFactoryBean.getServiceFactory().getService();
> List<ClassResourceInfo> list = ((JAXRSServiceImpl)service).getClassResourceInfos();
>
> They can also be retrieved at runtime from the current message:
>
> Service service = message.getExchange().get(Service.class);
> List<ClassResourceInfo> resources = ((JAXRSServiceImpl)service).getClassResourceInfos();
>
> In order to get the list if all the jaxrs endpoints you'd need to get
> a DestinationRegistryManager extension from the bus and enumerate over all the destinations and those which return
> null for getEndpointInfo().getInterface() do represent restful endpoints :-) so if possible try the services page for
> the latter task :-)
>
> Sergey
>
>
>>


-- 
Marko Voß
ePublishing & eScience
Development & Applied Research
Phone +49 7247 808-744
Fax +49 7247 808-133
marko.voss@fiz-karlsruhe.de


FIZ Karlsruhe - Leibniz Institute for Information Infrastructure
Hermann-von-Helmholtz-Platz 1
76344 Eggenstein-Leopoldshafen, Germany

www.fiz-karlsruhe.de


-------------------------------------------------------

Fachinformationszentrum Karlsruhe, Gesellschaft für wissenschaftlich-technische Information mbH. 
Sitz der Gesellschaft: Eggenstein-Leopoldshafen, Amtsgericht Mannheim HRB 101892. 
Geschäftsführerin: Sabine Brünger-Weilandt. 
Vorsitzender des Aufsichtsrats: MinDirig Dr. Thomas Greiner.



Re: Easy and quick access to existing JAX-RS interface endpoints

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Marko
On 02/04/12 15:34, Voß, Marko wrote:
> Hello,
>
> I need to know the existing endpoints of a JAX-RS interface.
>

The services page should return the list of all the REST (& WS) 
endpoints available and then individual WADL instances will describe all 
the root resources which constitute a given endpoint,

> I did the following solution first:
>
> List<ClassResourceInfo>  resources = jaxrsServerFactoryBean.getServiceFactory().getClassResourceInfo();
> for (ClassResourceInfo resource : resources) {
>       if (FooRestService.class.isAssignableFrom(resource.getServiceClass())) {
>           LOG.warn("Foo REST-Service locally available!");
>           LOG.warn("Service path: " + resource.getPath().value());
>           for (OperationResourceInfo ori : resource.getMethodDispatcher().getOperationResourceInfos()) {
>               if (ori.getAnnotatedMethod().getName().equals("retrieve")) {
>                   LOG.warn("Method path: " + ori.getAnnotatedMethod().getAnnotation(Path.class).value());
>               }
>           }
>       }
> }
>
> Output:
>
> Foo REST-Service locally available!
> Service path: /foo/something
> Method path: /{id}
>
>
> This solution however may not work, when dealing with distributed services. One server instance may not have all
> services registered to its jaxrs:server bean configured in Spring.
>
> What we do have available on all instances are the JAX-RS interfaces because of we need to perform requests to the other
> instances of course.
>
> So, is there an easy way to get all the endpoints or do I have to implement the reflection on my own?
>
> I do know, that CXF is already handling this in some classes. I tried the following, which does not work, because the
> iteration has no items to iterate through. I would prefer to reuse the existing code in CXF for this.
>
> JAXRSServiceFactoryBean serviceFactoryBean = new JAXRSServiceFactoryBean();
> serviceFactoryBean.setResourceClass(FooRestServiceImpl.class);
> Service service = serviceFactoryBean.create();
> for (Endpoint endpoint : service.getEndpoints().values()) {
>       LOG.warn("Endpoints: " + endpoint.getEndpointInfo());
> }
>
> Output:
>
> <nothing>
Right now the model representing JAX-RS endpoints and the CXF model 
which is optimized for representing WS service and endpoints are not 
closely related, there's a link but it's not a 1 to 1 match,
the following will only give you the list of all the root resource for a 
current endpoint.

Service service = serverFactoryBean.getServiceFactory().getService();
List<ClassResourceInfo> list = 
((JAXRSServiceImpl)service).getClassResourceInfos();

They can also be retrieved at runtime from the current message:

Service service = message.getExchange().get(Service.class);
         List<ClassResourceInfo> resources = 
((JAXRSServiceImpl)service).getClassResourceInfos();

In order to get the list if all the jaxrs endpoints you'd need to get
a DestinationRegistryManager extension from the bus and enumerate over 
all the destinations and those which return
null for getEndpointInfo().getInterface() do represent restful endpoints 
:-) so if possible try the services page for the latter task :-)

Sergey


>