Including JSTL implementation jar only - java

Following this answer, below is a simple JSP demo that includes only JSTL implementation jar(javax.servlet.jsp.jstl-1.2.1.jar), but not JSTL API jar(javax.servlet.jsp.jstl-api-1.2.1.jar),
My understanding is, JSTL implementation jar holds both API(mostly Java interfaces) and it's implementation. This is the reason test.jsp got compiled and executed successfully.
Further, same approach would work with servlets using API implementation jar provided by Tomcat container without using API(servlet-api.jar).
Is this the right understanding?

Api contains only interfaces you need to compile your code. The implementation could be in different library.
Tomcat and any other Java web servers provide implementation at runtime, so you don't need to package implemented classed and carry on them with your app.
You could see in the logs if implementation is already loaded if you deploy your application that contains classes impl.

Related

What's is the difference between api and just jar files?

In .gradle/caches/transform-3/... there is jetified-facebook-login-5.15.3.jar and jetified-facebook-login-5.15.3-api.jar
I'm also assuming jetified-facebook-login-5.15.3.api.jar can be imported to a project so that one can use Facebook related api functions in his/her project.
Is the other one just a javapackage an the other javadoc?
Whats the use for each one of them?
Is the other one just a javapackage an the other javadoc?
When you see such a separation, then the -api is usually just an api definition (interfaces and their refered classes), the default jar usually contains a complete implementation.
This is used often when you have some runtime environment providing the implementation.
A clear example is servlet-api.jar and servlet.jar - when creating a web application to run on an application server, you may need the servlet-api to compile and build the web app. But the actual implementation of the servlet infrastructure will be provided by the application server itself.

How to differentiate an implementation from specification

Assume that I have a simple servlet program which requires only the web container. Also assume that I am not using an IDE to compile this program. I can compile my program as follows.
javac -classpath /path/tomcat/common/lib/servlet-api.jar -d classes src/Ch1Servlet.java
I have been said by some people that servlet-api.jar just contains the specification, and the implementation is provided by the tomcat server. This confuses me.
If I compiled a program using a library, I still need the same library when I am running the program also. Therefore at some point Tomcat has to use the same library specified above (servlet-api.jar) when running the application.
What is really meant by implementation and specification? What makes a code just a specification? An example in code would be really helpful.
A library contains declaration - Interface which fixes method. E.g.
public interface SaveInterface {
void save();
}
You use the interface to save your data but implementation could be different. Tomcat saves the content here adn another application there. All depends on real implementation. But you in your logic don't care how it's implemented. You use the interface.
Interfaces/Abstract classes contribute to a spec and the actual implementation of it is what is used by us as the 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).

Do I have to compile my java web app classes against a certain servlet container?

I'm a long time ASP.NET developer trying to teach myself java. I've got Jetty downloaded and a basic web app setup. The tutorials in Head First Servlets and JSP tell me to reference the container's servlet-api.jar (or servlet-api-3.0.jar in Jetty's case) file when compiling, which makes sense since I'm extending the servlet classes and all, but doesn't this tie my application to a specific container's servlet implementation? If I compile my app against Jetty, can I still deploy the app under Tomcat or any of the EE servers (glassfish, jboss, etc...)?
No, this shouldn't be a problem because you aren't referencing servlet-specific classes. servlet-api.jar is a well-documented specification in the form of several interfaces and abstract classes.
Every container has to have a copy of this JAR (possibly compiled using different Java version, or compiler) because it implements the specification, but the API itself never changes. However note that you don't really have to reference container-provided JARs. You can safely use maven's version or any other you can find. They are all compatible. Sometimes they are not bundled due to various licensing incompatibilities.
That being said: write once, run everywhere applies here as well.
You aren't coding to the jar, you are coding to a specification which the jar happens to contain. Any server providing a web container will have an implementation of this specification, the jar which it is contained in is totally irrelevant.
As long as you only code to the specification, then you are not bound to any server implementation.
The jars are used at compile and runtime to resolve the necessary class dependencies you have. You can use any jar which provides the necessary API dependencies at compile time, but at runtime you will implicitly be using the implementation provided by the specific server. I say implicitly since you do not have to do any specific configuration for your own webapp to include the standard API or it's implementation, the server will already provide that for you, unlike a standalone app.

JAX-RS in relation to Jersey and JSRs

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.

Categories