JAX-RS in relation to Jersey and JSRs - java

I'm trying to get my head around some concepts in Java:
JSR(s): describe specifications, but carry no actual implementations. E.g. http://jsr311.java.net/ is the "home" for "Java™ API for RESTful Web Services". It serves as a common reference for all implementations of JSR-311.
One can download the interfaces (?) of JSR-311 from http://mvnrepository.com/artifact/javax.ws.rs/jsr311-api, however, unless you are implementing JSR-311 by yourself these have no particular value?
JSR(s) will usually/always have a reference implementation. To find it you'll have to google "JSR XXX reference implementation" or see the specifications home page (e.g. http://jsr311.java.net/)
For JSR-311 this reference implementation is Jersey. Using maven you can get the jersey server from http://mvnrepository.com/artifact/com.sun.jersey/jersey-server/1.9. Since
Jersey provides an implementation according to the interfaces found in http://mvnrepository.com/artifact/javax.ws.rs/jsr311-api, you only need to add Jersey as a dependency in your project and not the jsr311-api itself. (this applies to all JSR technologies?)
Putting both http://mvnrepository.com/artifact/javax.ws.rs/jsr311-api and http://mvnrepository.com/artifact/com.sun.jersey/jersey-server/1.9 as dependencies in your project will possibly cause classpath problems?
Am I completely off or onto someting?

Yes, this isn't anything new. Think about JDBC, java provides the
interfaces (Connection, Statement, ResultSet etc) but it is up
to database vendors to provide implementations.
If you're using a JSR-311 implementation like Jersey or Apache CXF
then you'll annotate your classes with the javax.ws.rs annotations, such as #Path, #GET, #Produces etc. This is why you need to explicitly have JSR-311 as a maven dependency.
Yes, usually. Have a look at the JSR list on wiki.
You need both the JSR and the implementation. The annotations are in the JSR, the implementation provides supporting classes, such as com.sun.jersey.spi.container.servlet.ServletContainer.
No, it is necessary to have both as dependencies (see point 4); you won't get classpath conflicts.

—
One can download files from a variety of sources. To get the most official version of the JSR-311 specification go to its JCP download page. It's quite possible that you can't get a JAR file (with all the interfaces and stuff) from JCP pages, but still, this is the official source. (There are always nice PDFs of public drafts also!)
—
You're right, because Jersey contains the API defined by JSR-311, however I would add a compile dependency to the jsr311-api JAR file and add Jersey as runtime dependency. This creates a nice separation between API and implementation and you can swap out your JSR-311 implementation anytime [sic]. If you intend to use Jersey all the way include only Jersey. One less dependency in your POM.
If Jersey packages the same API as the jsr311-api JAR contains, it won't. If it packages something different, well, that would be awful! Maven will probably bark at compile time if one has a corrupt JSR-311 API on its classpath (I've already seen lots of java.lang.ClassFormatError: Absent Code attribute in method that ... errors, so it won't go unnoticed, that's for sure).
Other than these, you're right.

Related

How to resolve jersey.internal.RuntimeDelegateImpl with Jersey on OSGi

Im am using Jersey in an OSGi environment. I wrapped all Jetty and Jersey jars in one bundle containing also my own server / servlet / resource abstraction. This is running quite well. I am importing the javax.ws.rs-api via OSGi package import because related packages are also used by JAX-RS resource implementations in other bundles.
However, from time to time my implementation does not work with an "java.lang.ClassNotFoundException: org.glassfish.jersey.internal.RuntimeDelegateImpl cannot be found by javax.ws.rs-api_2.1.0".
It seems this could be a race condition. Maybe Jersey sometimes uses a class from my internal bundles and sometimes a class from imported javax. I cannot really figure out what the problem is.
The problem is similar to [1], but in my case it is not about any import or dependency. I wrapped the Jetty and Jersey Jars in an OSGi bundle.
[1] org.glassfish.jersey.internal.RuntimeDelegateImpl NOT FOUND
This problem occurs because the JAX-RS API uses many static methods to get hold of implementation types from the JAX-RS provider. In this case the error isn't coming from Jersey, but actually from the JAX-RS API itself when it tries to find an implementation of the various JAX-RS interfaces.
You effectively have four options:
Avoid exposing the JAX-RS API from your server by putting all the resources in there as well (I don't recommend this option!)
Embed the JAX-RS API in your existing Jetty/Jersey uber bundle and export it from there. Be careful to include the correct API package versions and contract capabilities! (This option is fiddly)
Use an OSGi-aware API bundle (such as one from Apache Aries, Apache Geronimo or Apache Service Mix). Many Java EE API bundles (JAX-RS included) package themselves as OSGi bundles, but ignore the fact that they actually need to work in OSGi, which means that you can't rely on reflectively loading types/resources from a flat classpath. (This option is probably quickest and lets you keep working as you are)
Move to using the new OSGi JAX-RS whiteboard from OSGi Release 7. The reference implementation for this is in Apache Aries and available on GitHub (This is the best long term option from an OSGi perspective, and means that you can avoid maintaining your own server)
I hope this all makes sense, explains why you're seeing the error, and hopefully gives you some options for working through the problem.

Maven3 - can I declare "some implementation of api xy" is needed

I split up my projects into multi-module projects often and heavily.
How can I declare in the Maven 3 POM that "Some implementation of API xy has to be available in the package".
For example, if I split my services layer in a services-api and services-impl and declare in the API that the deployable has to have a dependency on an implementation of services-api, even if its not the services-impl module itself.
Is this possible?
If you need an implementation of an API, then something has to choose which impl. If you don't care which, you have then 2 choices:
Either you just choose an impl and declare it in the POM, using <scope>runtime</scope>, which excludes the impl at compile time, but it will be made available to the container.
Or you use or implement a Service Provider Interface (SPI)
To quote from the Oracle tutorial (emphasis added):
A set of programming interfaces and classes that provide access to some specific application functionality or feature. The service can define the interfaces for the functionality and a way to retrieve an implementation.

How does Java find a specification implementation?

I don't understand how java knows an implementation of any spec..
For example, I have a Spring App with JSF, if I place the Mojarra jar on classpath the app works, but I have not done nothing but that add it to classpath, all without configuration
If I take out the Mojarra jar, then my app doesn't works.
Even, How it can differenciate between Mojarra or MyFaces without any change?
I just want to know how Java finds the implementations, not why it doesn't work if I take out the jars ;)
Usually the Java spec classes are divided in two parts:
An API part(jar) that contains mainly interfaces usually provided by the spec guys.
An implementation part(jar) that contain the implementations of these interfaces.
An example of the above is JDBC: javax.sql.* classes are provided by sun/oracle, but the implementation is done in the JDBC drivers provided by each db vendor. In this case some kind of configuration is needed in order to "map" the API to its implementation because you use API classes only.
Your example with JSF is a little different in that both Mojarra and MyFaces contains the API classes from javax.faces.* package, basically there are different classes with the same names. So there is no need for configuration, the classes have the same name in both libraries and are loaded by the class loader whenever needed from the Mojarra or MyFaces jars whichever is on the classpath.
I have found MyFaces and Mojarra Implementation for JSF. I have realized that both has same pachage structure so it means that all are compliance with JSF spec. In other word which implementation jar is given into classpath classpath loader will handle it.
It is all about Java Class Loader mechanism of JVM. You can find detailed discussion at Java Class Loaders
Here is the picture of both JSF implemantation package structure.
I've seen the mojarra jar (JSF Reference Implementation) and I found that it uses The Service Loader API, since it places the javax.servlet.ServletContainerInitializer, javax.enterprise.inject.spi.Extension and com.sun.faces.spi.injectionprovider inside the /META-INF/services folder in the javax.faces-2.2.0.jar.
This is how java distinguishes between an implementation and another (mojarra or myfaces).

Declaring JAXB as a dependency. Why?

Why would you want to declare JAXB as a dependency of your Java application since it's anyway shipped with the JRE and cannot be overriden in your applications classpath?
Using the jersey-json as an example, in their POM file they declare a dependency to jaxb-impl without specifying the exact version even. What are they gaining by doing this?
And also, when I add a dependency to jersey-json in my own POM file, I end up having jaxb-api.jar and jaxb-impl.jar in my classpath. Why would I want this to happen? Isn't the default JVM implementation anyway getting loaded if I don't put the files to the endorsed libraries directory?
I'm seeing in the linked pom:
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
</dependency>
But there is also a parent pom, so you might want to follow that trail up, to see if an actual version and/or scope was specified there (and propagated down).
But if it isn't, then I'm guessing the Jersey team felt that the JAXB 2 API is mature enough to allow them to specify a loose dependency on the JAXB implementation.
The JRE ships with a specific implementation of the JAXB impl, which was equivalent to JAXB RI 2.1.7 for the longest time. But at the same time, there is a mechanism to easily swap out for another implementation of your choice, in your apps.
Sure you can use the built-in JRE JAXB implementation, and if it works for your app, you surely should try.
Nonetheless, some reasons that could lead you to want a separate JAXB implementation include : a left-over bug (addressed in a newer release); need a newer JAXB API such as JAXB 2.2.x (which comes in more recent version of the JRE); want to use a different implementation altogether (because it happens to have a better API and/or performance for your particular usage), etc...
So back to your jersey question, I'm guessing again that they wanted to give developers the flexibility to pull in their JAXB impl of choice. I'd think they have some level of recommendations somewhere in their guides.
However, the fact that the JAXB RI is specifically marked as a dependency, undercuts the argument.
That sound like the jersey people defined their dependency wrong. If a dependency is provided by the environment where you run it should be defined with the scope "provided".

Runtime code injection

SLF4J has a nice mechanism, where the implementation is chosen at runtime, depending of what is available in the classpath. I would like to use such feature in several projects, for example to choose the communication layer or to choose a mock implementation.
I had a look at slf4j source to see how it's done and I could just write something similar. Before I start, I would like to know if some lightweight FOSS library exists for this kind of injection.
Unless you need specific configuration abilities as provided by Pico or Guice, you may get what you need from java.util.ServiceLoader.
Basically, all you have to do is to package your service implementation in a JAR file, include a text file with a list of all implementation classes in "META-INF/services/" and on you go.
Have you looked at Weld, CDI is part of the EE6 spec but the Weld implementation also supports running in a Java SE environment. It has exactly what you are looking for, here is a link to the relative documentation:
http://seamframework.org/Weld one maven dependency for your SE app.
http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html/environments.html#d0e5333 bootstrapping the Weld container in SE.
Producer methods to vary implementation at runtime:
http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html/producermethods.html
Plus (in my very biased opinion) Weld rocks ;)
SLF4J's "mechanism" is simply that its API jar is compiled with code that refers to a class that is only provided by one of its "implementation" jars. No framework or library of any kind is needed for this. Simply write one module which is compiled against a class not in that module. Then your "implementation" modules provide that class when included in the project.
Edit: Oh, and this is basically OSGi writ small (very, very small). If you're going to use this kind of thing on a large scale, look to an OSGi container or Eclipse Virgo.
Every java programmer should know how to use Spring.

Categories