Use JAX-RS without being implementation specific - java

I have a service that I want to consume in a few projects in basically the same way. I'd like to simplify the process of sending and receiving data to and from these projects, so I would like to make a client jar that handles the process of packing and unpacking jaxrs responses/requests and include that in my other projects.
However, to use any jax-rs objects, I have to be dependent on a specific implementation of jax-rs. In my little client library I have to include jersey (or resteasy or cxf) to have access to any of the jax-rs imports. If I were to include this jar in any of my other projects, they'd be forced to use that rest implementation as well.
Is there a way to create a single project jar that utilizes jax-rs objects, that would use the jax-rs implementation of the consuming container instead of having many nearly identical client projects that just include a different jax-rs implementation?
Essentially, I want my project wars to include a jar that will handle packing and unpacking jax-rs rest objects that use whatever implementation of jax-rs the war project uses.

Classes from the javax.ws.rs.* package are portable and are expected to work across different JAX-RS implementations. Use the following dependency:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
Classes from the following packages are implementation specific and you don't want to use them directly when you want your code to be portable across different implementations:
Jersey: org.glassfish.jersey.*
RESTEasy: org.jboss.resteasy.*
Apache CXF: org.apache.cxf.jaxrs.*
However such classes must be in the classpath during runtime.
The JAX-RS Client API was introduced in JAX-RS 2.0 and enhanced in JAX-RS 2.1 with reactive capabilities. Check the API documentation for details.
Prior JAX-RS 2.0, any client support was vendor specific and not portable. The proxy-based clients provided by most of the vendors are not portable either.
The JAX-RS Client API can be used as follows:
Client client = ClientBuilder.newClient();
Response response = client.target("http://example.org/hello").request("text/plain").get();
In the above code, a javax.ws.rs.client.Client instance will be created using the default javax.ws.rs.client.ClientBuilder implementation class provided by the JAX-RS implementation provider.
If you are interested, check the documentation for the Client implementations:
Jersey: org.glassfish.jersey.client.JerseyClient
RESTEasy: org.jboss.resteasy.client.jaxrs.ResteasyClient
Apache CXF: org.apache.cxf.jaxrs.client.spec.ClientImpl

Related

NameBinding missing from jsr311-api

I am using the answer here to implement authentication on a jax-rs REST endpoint running on WebSphere Application Server.
Eclipse is telling me that it can't find #NameBinding anywhere in the classpath.
pom:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.0</version>
</dependency>
As I understand it, I can't use a different version of JSR because WAS 8.5.5 only supports JAX-RS 1.1 (see WAS API Docs and the JSR Specification it links to
I now understand that NameBinding is not available in the 3.11 spec; so what's my alternative?
You can bring your own JAX-RS 2.0 API and implementation and configure your application to use that. Two major steps:
Disable the JAX-RS engine in WAS: https://www.ibm.com/docs/en/was/8.5.5?topic=djrwa-disabling-jax-rs-runtime-environment (the most important part there is setting the JVM custom property com.ibm.websphere.jaxrs.server.DisableIBMJAXRSEngine to true).
Put your desired API and implementation jars in a shared library, select the option to use an isolated class loader for the library (so it loads its own classes in preference to the server's), and associate that shared library with the server.
With that configuration, the server will avoid starting its own JAX-RS component or processing JAX-RS annotations, and the application will get its JAX-RS API and implementation classes from the shared library.

Differences between netflix.feign & openfeign

Introduction
I recently used netflix feign along with ribbon which was quite useful.
An Example of this is:
#FeignClient(name = "ldap-proxy")
public interface LdapProxyClient {
#RequestMapping(path = "/ldap-proxy/v1/users/{userNameOrEMail}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
LdapUser search(#PathVariable("userNameOrEMail") String userNameOrEMail);
}
However, at some point I thought that instead of having to code all these definitions by hand (for an existing webservice), that I should see if a tool existed.
I stumbled across https://github.com/swagger-api/swagger-codegenand saw that there are examples in which clients are generated, e.g. https://github.com/swagger-api/swagger-codegen/tree/master/samples/client/petstore/java/feign .
However, once I looked closely at the imports I noticed the following:
import feign.Feign;
Netflix's opensource solution on the other hand has package names:
org.springframework.cloud.netflix.feign.
Additionally, I noticed that both use ribbon if available, but Netflix's notation is much cleaner with a lot happenning in the background. E.g. the #FeignClient annotation class javadoc states:
Annotation for interfaces declaring that a REST client with that interface should be * created (e.g. for autowiring into another
component). If ribbon is available it will be * used to load balance
the backend requests, and the load balancer can be configured * using
a #RibbonClient with the same name (i.e. value) as the
feign client.
However in the Feign.feign documentation (at https://github.com/OpenFeign/feign ) I see:
RibbonClient overrides URL resolution of Feign's client, adding smart routing and resiliency capabilities provided by Ribbon.
Integration requires you to pass your ribbon client name as the host
part of the url, for example myAppProd.
> MyService api =
> Feign.builder().client(RibbonClient.create()).target(MyService.class,
> "https://myAppProd");
So my questions are:
what is the history/relationship and differences between the two?
what are the pros and cons of each?
Are they completely different projects with no relation, or did netflix just fork/utilize OpenFeign and modify it to be within their integrated cloud solution? Essentially, did netflix just acquire and integrate different technologies like Discovery, ribbon, and feign from open-source projects?
"Netflix feign" is the old project designation. The last version (dependency below) is dated July 2016.
compile group: 'com.netflix.feign', name: 'feign-core', version:'8.18.0' // OLD
"Open feign" is the new project designation. It's the same project, but was moved to a different git repo and got a new group-id. Its versions start at 9.0.0.
compile group: 'io.github.openfeign', name: 'feign-core', version: '10.0.1' // NEW
See this github issue for a brief history of what happened. Most remarkably, you'll find out that Feign isn't used internally at Netflix anymore. :^o
org.springframework.cloud.netflix.feign is a part of Spring Cloud Netflix project which is a part of Spring Cloud.
Spring Cloud uses OpenFeign under the hood. It extends it to support Spring MVC annotations and makes it a first-class citizen in the Spring Environment by providing integrations for Spring Boot apps through autoconfiguration.
From the documentation:
Feign is a declarative web service client. Spring Cloud adds support
for Spring MVC annotations and for using the same
HttpMessageConverters used by default in Spring Web. Spring Cloud
integrates Ribbon and Eureka to provide a load balanced http client
when using Feign.
Note that in the documentation there is a link to OpenFeign project.
So if you use Spring Boot - it is better and easier to use Spring Cloud OpenFeign integrations.
See also the source code.

Java rest framework with programmable dispatcher?

I'm searching a java rest framework or JAX-RS implementation that allows me to configure the dispatcher at runtime through an API. In JAX-RS it is only possible to do the configuration with #Path and #HttpMethod annotations or by effectively building your own dispatcher in a sub-resource.
I'm searching for:
dispatcher.addResource("/my/{path}", Resource.class) or
dispatcher.addResource("/2nd/path", resourceHandlerFactory)
Unfortunately there is nothing in JAX-RS for dynamic resource specification as you've found. Apache Wink has another alternative to Restlet called DynamicResource http://incubator.apache.org/wink/1.1/html/5.1%20Registration%20and%20Configuration.html. I'd be quite interested in why you need dynamic resources as I had similar requirement.
Try Restlet. It provides runtime dispatch functionality through its Router class. See http://wiki.restlet.org/docs_2.1/13-restlet/27-restlet/326-restlet.html for an example.

Exposing the web service using CXF

I have a requirement to expose a webservice using CXF. I am following this easy tutorial link text and did the following steps
Created a service and an implementation with #WebService annotations
Added the standard xml snippet of including cxf.xml and other xmls specified
Now I need to deploy this webservice in multiple containers. In a normal web app, I just added the CXF Servlet config but I have another application which is a bespoke framework built on top of Jetty and some handlers/exporters where there is no specific web.xml as such. In such a scenario is there any spring configuration which when declared does the equivalent of this servlet configuration bit?

Developing Web services applications from existing WSDL files

I have done this on Websphere (re: title of this topic) using wsdl2java for generating wsdl to java mapping xml file.
My endpoint is a generic stateless EJB. The code in EJB is generated by traversing the each wsdl and getting the wsdl operation and stuck it in the generated remote EJB interface.
Each EJB method impl is generic and handles all the services the same.
Used instructions on this doc to do this on WAS: http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.base.doc/info/aes/ae/twbs_devwbsjaxrpcwsdl.html
Now, I am asking you all for help if anyone has done something similar in Sun AS 9.1.
Starting from existing WSDL (and xsd) files. Knowing the sole EJB service endpoint implementation for each services are the same, and generating an EAR file (webservices.xml, ejb-jar.xml, etc).
Have struggled with wscompile and alike, but not getting anyware in the same fashion I did for WebSphere.
Thanks for help.
You want to create a WS client which runs under Sun AS? I don't know Sun AS in detail and I don't know the WS libraries it supplies. But you may want to use a public WS library:
Apache Axis 2
Apache CXF
For every library there is documentation which describes how to create a project from WSDL.
You could even use Eclipse to create a project from WSDL for you: File -> New -> Other... -> Web Services -> WSDL. Make sure you have the "WST Web Services" Plugins installed.
I've never used it myself, but I just recently read about the wsdlLocation() attribute of the WebService annotation, which is supposed to map the service to a preexisting WSDL document (not sure if you're even using EJB3, though).

Categories

Resources