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.
Related
I want to use a javamoney lib, I found two lib the below:
javamoney/jsr354-api and javamoney/jsr354-ri in the github. What's the diffirence, thank you.
ri in jsr354-ri stands for reference implementation, and api in
jsr354-api stands for the programming interface without the implementation.
You'd use api to program against and implementation is needed runtime to actually execute your code. Reference implementation means it's the "official" implementation version.
I'm building a plugin-based program in Java, whereby I want to keep the project closed-source, but allow 3rd-party developers to create plugins. The system I'm using is working, but only because I (of course) have full access to the source code.
Basically, the plugins inherit from Plugin.java, and they may make use of ServerManager.java in order to perform certain critical functions. How do I make it such that users are able to see the interface of these classes (i.e. they know that ServerManager has a sendMessage() function and that Plugin classes can override an onMessage() function) without supplying them with the full source.
Coming from an Objective-C background, I'd use .h files for these "interfaces" and .m files for the source (private) – I'd then only supply the .h files – obviously in Java there's no such thing as a .h file though!
Thanks in advance :)
One method is to create an interface, let that be public, and provide an implementation of that interface.
For example:
interface Light{
void turnOn();
void turnO();
void setBrightness(int newValue);
void setTimer(int timeoutSeconds);
}
Then you define your actual class in a private file:
class MyLight implements Light {
void turnOn() {
// implementation
}
// etc..
}
You can provide a Factory class that churns out MyLight objects for the user.
For that java has the SPI, Service Provider Interface. Here an article.
The mechanism is having an interface, publically available, best in its own library.
The (several) implementors provide a jar, with one (or more) implementing classes specified in a text file with the interface name under META-INF.
Then java has an API to pick one implementation, or list all.
It is a relative simple and versatile mechanism, look into the official javadoc. For XML implementations it is used.
If you want that anyone doesn't see your core code then you can obfuscate the required code, the part you want to expose to client to create a plugin can be skipped from obfuscation.
You can dot the similar thing here. Crate an opensource interface and the client will do the implementations on his side.
Most of the java EE world works this way. For example you have a interface definitions like this http://jsr311.java.net/nonav/javadoc/index.html and have multiple different vendor imepmentations. Similarly your code will have an interfaces that you would use to access the plugins.
One similar implementation is done by Atlassian Confluence where the product is closed source unless you have a specific licence for the source but the plugin development is completely separated : https://developer.atlassian.com/display/CONFDEV/Confluence+Plugin+Guide
I have an application that is developed in Java that has nice GUI and all. I don't have the source code and also the dll's of that. But I have the compiled classes of that application (.jar files).
Now, I want to automate that application. I mean the application needs manual intervention.
Can I use that compiled classes so that I can use its functions to automate the functionality of that application?
If so, how would this be done?
You shouldn't have to "got the compiled classes out of that application (.jar)". A better idea would be to treat it just like any other 3rd party JAR and add it to your CLASSPATH when you compile and run.
You'll write your own class that instantiates an instance of that 3rd party class and calls its methods, just like any class you get from the JDK.
You may not be able to alter that class; you might not want to even if you could.
If you must have new functionality, the OO way would suggest that you should extend that class, if you can, and override its method according to your needs.
Put that .jar into your classpath and use what ever you want from that application. If you need to use private fields or methods also you can use Reflection API for that. There is no restrictions of using objects from .jar file.
You should beware of infringing on any copyrights if the application you are referring to is proprietary. Otherwise, any java decompiler will get you the source code from those class files.
I'm confused with the role -classpath option plays in both compiling and running a java program. Please help me understand.
Because they are two separate operations and not necessarily the same paths.
The runtime dependencies are often more extensive than the compile time dependencies. For example, many programs will code to interfaces, which limits the compile time dependencies to those interfaces. At runtime, the VM must be able to resolve the implementations of those interfaces, which are not required until they are loaded at runtime.
it simply in both cases tells javac and java where to find dependencies required for your program to both compile and run
The reason it is done twice is that the environment you compile the code in may not be the same environment you run the code in.
Java loads classes at runtime. For example, you could write a method that forces loading of class X, compile it, write class X, compile it, and then run them together. In addition, you typically refer to classes by a fully specified name, but could run the same program with different versions of that class (e.g., a different version of the library). Thus, you need to tell Java where it could potentially find the classes that it needs to load.
As for compilation, to ensure type safety, you have to provide the Java compiler at least with the interfaces or base classes that you are referring to and making calls on, so that the compiler can at least ensure that the call would be legal. For that reason, you have to tell it where to find the jars containing them.
Here is an example. Let's say you want to use JMS (a messaging framework) in a core Java program. At compile time, you need to at least tell javac where to find the JMS interfaces. At runtime, you need to provide these interfaces, but you also need to provide the JAR with the actual implementation (e.g., ActiveMQ).
In C++ I believe it is the case that linking happens around compile-time, to create an executable (I am not a C++ programmer so I'm not sure about that).
In Java, the linker step happens at runtime (see the JVM spec, "Loading, Linking and Initalizing"). From your question it sounds like you understand why the classpath needs to be specified at compile time (because you might reference classes from third-party JARs in your code), so I will just explain that when your program is being run, those classes are not loaded into the JVM until they are referenced. At this point, the JVM needs to know where to find their representation.
The compiler has to know where to look to satisfy compile-time dependencies.
The VM has to know where to look to satisfy runtime dependencies.
At compile time, you need to tell javac where to find third-party and user-defined classes. At runtime, you also need to tell java where to find third-party and user-defined classes. In both cases, one way to change the class path is to use the JDK Tools' -classpath option. Checkout the Setting the Class Path technical note for more details.
Is it possible to specify a custom classloader for javac (or some alternative java compiler)?
I'd love such a feat because it would allow me to compile classes that use classes that are only found by my special classloader.
For the curious ones: I'd write a classloder that connects to a database and creates classes based on the tables it finds.
When you run javac you can specify the classloader like so:
javac -J-Djava.system.class.loader=org.awesome.classloader sourcefile.java
It may be possible to initialize a custom classloader and then use it while calling the new Java 6 Compiler API in javax.tools.
The only two ways I know of plugging directly into javac (as run on the command line) are via the annotation processor or via a compiler-specific hack.
Just to expand on Michael's answer, if you cannot use Java6, look at the sun. packages--they have always been available to java apps and have always had a compiler in there, it's just not standard Java so you don't hear about it much and the API is subject to change (like moving it to the javax.tools package!)
Take a look at ClassLoader.defineClass. I used it myself for loading plugins into a program I created, in which I loaded a file's bytes into a new class.
If the classes all conform to the same Interface you could just provide that at compile time..
If not then I don't see what you are gaining by not outputing .java files based on the DB and compiling that.