I created a program in Java and I designed it so that methods that I want them to appear (getter methods) in the main, I can call them easily after initiate the class that holds these methods.
The question is that, I need to make this application (that holds the getter methods) to be like an API so that I can give my application for developers to use my functions (the getter methods) if they need them, and only what they need is to add this file (I think the API after is done shown as .jar file).
How can I make it so that I can make my code reusable with other application? It's similar to the .dll, I think.
Thanks a lot ;)
Create a JAR. Then include the JAR. Any classes in that JAR will be available. Just make sure you protect your code if you are giving out an API. Don't expose any methods / properties to the end user that shouldn't be used.
Edit: In response to your comment, make sure you don't include the source when you package the JAR. Only include the class files. That's the best you can really do.
To be useable as an API, your classes should:
Use a unique package (ideally following the convention, i.e. the reverse of a domain you own as prefix). This prevents naming conflicts
Have only those classes and methods public or protected that are intended to be used by others. This makes it easier to use.
Have extensive Javadoc comments.
Be available as a JAR file - ideally separate JARs for binary distribution, source code and javadoc files.
You need to package your application as a jar file. You can use ant jar task to create jar files or you can use the jar command.
For ant tasks look at this link.
For creating it manually look at this link.
Make sure you write and publish javadocs for all your public and protected classes and methods.
To create the jar:
jar cf <jar_name> <sources>
There are several ways you can expose your code. Creating a jar and distributing that may be the easiest as other developers will just have to include your jar. However, if you are talking about "anyone" accessing your code, a web service may make more sense as you can provide access to the data without providing all of the necessary code. You mention providing access to your getters - if you just create a class that has getters, the other developers can use them, but how are they going to be populated? If your application is self contained in that it gets the necessary data and provides the getters, that should work, but if you are talking about providing access to data from your running application, a web service makes more sense as your application can retrieve the data and provide access via publicly accessible methods.
You most likely want to create interfaces as well so developers can code against the interface and you can change the internal workings without impacting them. Any API that will be used by others should be extensively documented as well.
Well, depends on your IDE. I use Netbeans, so I just hit build project, and viola! A jar file is created in my directory specified. Now, that's just for compiling. All anyone has to do is download your .jar file, and if in Netbeans, right click libraries, add jar/folder, and select the downloaded file.
You can also consider:
Include some samples that demonstrate how to use your library
Build your jar using Apache Maven
Put your jar in a public maven repository
Publish a new version of your library as you find/fix bugs
If you want to hide your implementation, you can pack your jar with obfuscation, so that if someone decompiles your classes, the code will be difficult to read
Related
I have a game written in Java and a whish to write a generic ModLoader/AddonLoader application. A separate application/api that would allow you to create mods/addons for my projects that add extra implementation that I do not want in the main application.
However I am not sure how to go about this, i've done some research and im not too sure how to make the mod/addon interact with a loader which interacts with the main application to add new features/modify old
Many Thanks
Elliott
Since you're looking for some basic guidance I'll suggest the following:
You need a way to pull in classes after the core application is running. That means you will need these classes on the classpath. The simplest way to do that is probably to have your classpath include a folder like "addons" so that all the jars in that folder are automatically on your application's classpath.
Once you have your classpath set up you will need to somehow make use of the appropriate class(es). This part is hard to speak generically about because it depends heavily on how you intend your addons to work. Some tools use annotations to help with this and you can probably look at some open source projects for examples. One that comes to mind is Maven, it makes use of annotations in its plugin system. The general concept is that you need to decide how many different kinds of addons you have and how you will identify them and make use of them.
Typically making use of an addon involves instantiating that addon which is why it can be tricky. Some plugin systems require that addons be written such that they use a specific package name. They do this so that they can make use of reflection to find all classes in a given package and then process them.
Hope that helps to get you started!
I am building a tool from several different open source libraries. My buildpath is in the following order:
My first JAR file, stanford-corenlp-3.3.0.jar, contains a package called edu.stanford.nlp.process, which has the Morphology.class class.
My second JAR file, ark-tweet-nlp-0.3.2.jar, contains an identical package name (edu.stanford.nlp.process), and an identical class name Morphology.class.
In both JARS, inside their respective Morphology classes there exists a method called stem(). However, the constructors for these methods are different. I want to use the stem(String, String) method from my second JAR file, but since the import statement (import edu.stanford.nlp.process.Morphology;) does not specify which JAR to use, I get an error since it thinks the first JAR on the buildpath is the one I want to implement.
I don't want to change the order of my buildpath since it would throw off my other method calls.
How can I specify which JAR's Morphology class to use? Is there an import statement that specifies the JAR, along with the package.class?
EDIT: What about a way to combine my two JARs so that the two Morphology classes merge, giving me two methods with different constructors?
As several others pointed out above, it is possible to tweak Java's classloader mechanism to load classes from certain places… but this is not what you are looking for, believe me.
You hit a known problem. Instead of worrying how to tell Java to use a class from one JAR and not from the other, you should consider using a different version of ArkTweet.
Fetch the ArkTweet JAR from Maven Central. It does not contain Stanford classes.
When you notice that people package third-party classes in their JARs, I'd recommend pointing out to them that this is generally not a good idea and to encourage them to refrain from doing so. If a project provides a runnable fat-jar including all dependencies, that is fine. But, it should not be the only JAR they provide. A plain JAR or set of JARs without any third-party code should also be offered. In the rare cases that third-party code was modified and must be included, it should be done under the package namespace of the provider, not of the original third-party.
Finally, for real solutions to building modular Java applications and handling classloader isolation, check out one of the several OSGi implementations or project Jigsaw.
The default ClassLoader will only load one of the jars, ignoring the second one, so this can't be done out of the box. Maybe a custom ClassLoader can help.
For more info about ClassLoaders start from here.
Good luck!
EDIT: We are looking at some horrible packaging choices causing as side effect this Jar Hell here. The author of this "Ark Twitter" library decided it was a good idea to release a JAR artifact that includes a third party library (the Stanford NLP library). This leads to unnecessarily tight coupling between Ark Twitter and the specific version of the Stanford NLP library used by it. This is a very bad practice that should be discouraged in any case: this violates the whole idea about transitive dependencies.
EDIT (continued): One possible (and hopefully working) solution is to rebuild the Ark Twitter JAR so that it does not include the aforementioned library but only its own code (basically the cmu.arktweetnlp package only) and hoping that the version of NLP required by your project works with Ark Twitter. Ideally you should submit a pull request to the author of the library but in the meantime you can get away with un-jarring and re-jarring the existing JAR file.
EDIT 2: Looking at the JAR file again, it's much worse that I originally thought: ALL the dependencies are repackaged in the released JAR file. This is really the worst possible solution for releasing a library. Good luck.
I think your problem can be solved simply by using the lemma(String word, String tag) method in the current CoreNLP's Morphology class:
String word = ...;
String tag = ...;
String lemma = morphology.lemma(word, tag);
WordTag wt = new WordTag(lemma, tag);
When the class was revised a couple of years ago, the method you're looking for was deleted. The feeling was that with most of the Stanford NLP code moving to using CoreLabels, methods that return WordTag are less useful (though deleting all such methods is still a work in progress).
No there isn't. This is a weakness of Java, that cannot be simply solved. You should use only one of the libraries. Having both on the classpath will make java always select the first one.
This problem is named as Jar hell.
The order in the buildpath generally determines the order in which the classloader will search for the class. In general, though, you don't want duplicates of the same class in your build path--and it sure doesn't seem like ark-tweet-nlp-0.3.2.jar should have a edu.stanford package within it.
When you load a class, it's loaded at given address, and that address is then placed in the header of objects created from the class, so that (among other things) the methods in the class can be located.
So if you somehow load ClassA, with method abc(String), from zip file XYZ.zip, that loads into address 12345. Then (using a class loader trick) you load another ClassA, with method abc(String, String), from zip file ZYX.zip, and that loads into address 67890.
Now create an instance of the first ClassA. In its header will the class address 12345. If you could somehow attempt to invoke the method abc(String,String) on that class, that method would not be found in the class at 12345. (In actuality, you will not even be able to attempt the call, since the verifier will stop you because, to it, the two classes are entirely different and you're trying to use one where the other is called for, just as if their names were entirely different.)
I have a library that I'm using in an Java application - it's important for certain functionality, but it's optional. Meaning that if the JAR file is not there, the program continues on without issue. I'd like to open source my program, but I can not include this library, which is necessary to compile the source code as I have numerous import statements to use the API. I don't want to maintain two code sets. What is the best way to remove the physical jar file from open source release, but still maintain the code to support it where other people could still compile it?
the typical approach taken is to define the wrapper API (i.e. interfaces) and include those interfaces in the open sourced code, and then provide configuration options where one can specify class names of classes that implement certain interfaces.
You will import API interfaces instead of importing classes directly into your open sourced code. This way, you are open sourcing the API but not the implementation of the parts that you do not want to open source or you cannot open source.
There are many examples, but take a look at JDBC API (interfaces) and JDBC drivers (implementation classes) for starters.
I was pretty much typing the same thing as smallworld with one addition. If this API were necessary you can use a project build tool like Maven to handle the dependencies on you project. If someone checks it out from source control with the pom they can download the dependencies for themselves and you don't have to include them in a source repo.
There's probably a number of ways to fix this, here's a couple I can think of:
If you have only a couple of methods you need to invoke in the 3rd party library, you could use reflection to invoke those methods. It creates really verbose code, that is hard to read though.
If you don't have too much of the API in the 3rd party library you use, you could also create a separate JAR file, containing just a non-functional shell of the classes in the library (just types with the same names and methods with the same signatures). You can then use this JAR to distribute and compile against. At run-time you'd replace it with the real JAR if available.
The most common way is probably to just create a wrapper API in a separate module/project for the code that is dependent on the 3rd party library, and possibly distribute a pre-built JAR. This might go against your wish to not maintain two code sets, but may prove to be the best and less painful solution in the long run.
I am very new to java and android development and to learn I am trying to start with an application to gather statistics and information like munin does. I am trying to be able to load "plugins" in my application. These plugins are already in the application but I don't want to have to invoke them all separately, but be able to iterate over them. I was trying to use serviceloader but could never get the META-INF/services into my apk. So I am wondering if it is possible to use serviceloader on android
Thanks
EDIT: I am asking about java.util.ServiceLoader, I think it should, but I can't figure out how to get my services folder into META-INF on the apk
There is an open bug report against this issue. See https://code.google.com/p/android/issues/detail?id=59658
The META-INF folder is deliberately excluded from the APK by ApkBuilder; the only comment in ApkBuilder.java is "we need to exclude some other folder (like /META-INF)" but there is no other explanation.
Even after adding META-INF with ant, you will still get in trouble if you want to use Proguard, which refuses to replace the content of META-INF/services/* files or rename them (that's another story, the author wants to keep Proguard agnostic).
However, people using maven may want to check https://github.com/pa314159/maven-android-plugin (the branch named "modified"), that tries to solve both issues. It is a fork from the original "android-maven-plugin" I modified one month ago for my own Android projects.
It also provides a patch for Proguard-4.7
Hope this helps, any feedback is welcome.
I've figured out a solution that may work for some situations. Instead of ServiceLoader, I'm using the org.openide.util.Lookup class / library that comes with NetBeans - it is a superset of ServiceLoader. It does not require NetBeans itself and seems to work ok with Eclipse. It is necessary to replace whatever ServiceLoader functionality you are using in your application with Lookup equivalents, and add the org-openide-util-lookup library. Then, you can just do something like this:
Lookup lookup = new ProxyLookup(Lookup.getDefault(),
Lookups.metaInfServices(myClass.getClassLoader(), "services/"));
And move your ServiceLoader files from META-INF/services/ to services/.
Note that, because of the ProxyLookup, this will continue to work on standard Java environments unchanged (i.e., in those cases it will continue to look in META-INF/services).
Here is a link to the documentation for the library: http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/org/openide/util/lookup/Lookups.html
UPDATE
After working with this for a couple of days, it seems to function well - I move between environments (standard Java and Android) and it works properly in each location. The primary downside is having to manually copy the files to the /services directory.
It is possible. You may want to check http://developer.android.com/reference/java/util/ServiceLoader.html
ServiceLoader is stuff from the Java language that is not really relevant on Android. I recommend not using it. If you just want to find a list of classes within your .apk to load, there are all kinds of ways to do this -- put in XMl file in res/xml that lists them, use reflection, annotations, etc.
How can I export a jar without some class or package which I don't want others to use,but which is needed in project,means I can't delete them.
This doesn't make a lot of sense.
If the classes are needed to compile the project, then there are likely to be static dependencies on them in other classes. (Otherwise ... you would be able to just delete it / them.)
But if there are static dependencies on those classes, then you won't be able to run the applications unless those classes are present in the JAR file. If you leave the classes out of the JAR to stop people using them (or whatever), your application will die on startup with "class not found" exceptions.
If you want to stop people using the classes directly, you could try the following:
Change the classes access to "package private". This doesn't make it impossible to use them, but it makes it more difficult.
Change your project so that the dependencies on the classes are entirely dynamic; e.g. via Class.forName(...) or dependency injection. Then you can exclude the classes from the JAR as required. But once again, if your application needs to use the classes, they have to be accessible at runtime (somehow), and it will therefore be possible (somehow) for other people to get hold of them.
Change your project to allow you remove the classes entirely. This is the only sure-fire solution.
Finally, before you go to all of this trouble you should ask yourself why you are even bothering to do this. Why don't you just let people use the classes anyway? What is to stop them getting the classes from somewhere else ... or implementing their own versions from scratch?
If the class is needed for your program to work, you can't omit it from the JAR.
You can put classes in a package that has something like "internal" in its name — e.g. com.example.internal — to indicate that the classes aren't meant for others to use or rely on. It can't prevent anyone from using your class for their own purposes, but it at least indicates that they do so at their own risk, that your internal interfaces might change in future versions of the program, etc.
A simple way is to use the package private access modifier for classes. That will make it difficult for others to access the classes, but it will also affect your ability to use them from other packages.
A more advanced way would be to use OSGi and only publish those classes you want others to use. That will make it impossible for others to access the classes while not restricting your access to them.
Put them into a separate jar file, include that jar file (as a single file, maybe with a nondescript name) into your jar file, create a custom class loader to open that embedded jar file from your code, bootstrap an entry point with reflection (because you cannot have static dependencies on it) into that new class loader .
Or just accept the fact that since the code is in there somewhere, any amount of obfuscation is just an inconvenience to everyone and cannot really hide anything.