How to use classes from another jar file dynamically - java

right now I am struggling with very specific problem. I am building modular app where most of the modules are strictly separated so there is no coupling. However some modules can use the same large parts of code so I thought of to make them as another modules and handle it via some dependency system to avoid building modules with the same parts of code.
My question is, as the modules are optional, is there a way how to build one module (jar file) dependent on another module? In other words, is it possible to build separate but coupled jar files I know they will be always together in specified file paths?
I would appreciate any suggestions, thanks.

In your first JAR, at the start in main method, check if the another JAR file is exists.
If it does not exist throw an error message and don't proceed till you find the second JAR file.

Related

How to share common files between several projects in Java

Suppose that I have a common directory that contains general-purpose files like FileUtils.java and ImageUtils.java. Also I have two projects that should use these common files. What is the most Java-way to import them into these projects? Just add path manually to the -classpath option when using javac and java? Build them into one jar file? Or something else?
Just follow simple steps:
1.) Have module say, companyname-commons-util
2.) build to a jar file, companyname-commons-util.jar
3.) Add dependency of this jar into other projects, and just reuse the classes. (maybe maven, gradle or explicitly adding into classpath)
** The same can be reused in other projects as well. Good from maintenance point of view, and keeping project structure intact.
The recommendation would be to create a third project and then use that to generate a JAR file; you can then use that reference in your other projects. If you're using Maven to build them you'd end up with a different module with your common code in place.
Besides the things that have been said; a word of warning: try to slice your projects aka components to be as small as possible.
In other words: before just blindly going forward and pushing all content of your "common" folder into its own project it might be worthwhile to step back and carefully look at
a) the contents of common
b) how other projects make use of that source
And theoretically, you match that whole picture with the thing that is called "architecture" (which may or may not exist for your overall "product") to understand where "reality differs from as-it-should-be".
Then, finally, you define one or more projects that cover all (or parts of) your source code in "common"; and then you change your whole infrastructure so that other "dependent" projects do not rely on using your "common" source files but some kind of build artifact.

Class-Path setting in executable jar doesn't seem to work for plugins

I've looked here and the wider web to find a solution to this. There's related material, but I've been unable to find anything useful about my specific question.
I'm working on some Java software that needs to accept plugins. I don't want to use a fancy framework like OSGi, and ServiceLoader seems to offer the right level of support. I've basically got it working but am having a problem with classpaths. My directory structure is as follows:
progfolder
|___________ plugintest.jar
|___________/plugins
|________ plugin1.jar
|________ plugin2.jar
If I run plugintest.jar with java -jar plugintest.jar then it doesn't find the plugins even if I add ./plugins/ (or variations of this) to the Class-Path: in the manifest. Reading suggests that this only works for classes, not jars, so I've tried putting the classes from the two plugins inside plugins both directly and within their full path of directories, but with no success.
I'm not allowed to add -cp plugins/* to add the plugins folder to the classpath if I'm using the -jar option. To get round this, I can run using java -cp plugintest.jar;plugins/* com.plugin.test.Main and this works as expected - the two plugins are detected and accessible via code, but the command line is a bit clunky, although I could live with it, if it's the best option.
I found another solution where I create a classloader for jars found in plugins, which works in this simple case, but reading suggests I might run into security issues in a more complex application.
Is there a way to fix things so I can simply run with java -jar plugintest.jar without having to do my own class loading or is this just the way it is?
Ok, so at least a partial answer, following more experimentation. Putting the class files in the plugins directory does work, after all, but you have to remember to include the META-INF directory and META-INF/services. The file in the services directory has to include references to all the plugins.
It would be nice if there was a solution that allowed the plugin jar files to be used directly, but creating a class loader seems to be the only way to do this (that I've found, at least), and this may cause security issues, as previously noted.
last time I faced with similar problem [1]. I found answer in java documentation [2]:
Note: The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file or classes accessible over Internet protocols. To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar.jar contains another JAR file called MyUtils.jar, you cannot use the Class-Path header in MyJar.jar's manifest to load classes in MyUtils.jar into the class path.
[1] https://github.com/narvi-blog/01-exec-jar#dependency-jar-files-within-an-executable-jar-are-not-so-easy
[2] https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html

Create a third pary library jar with JPA project

First off, I am pretty new to this. I am working on a desktop application which uses hibernate and an embedded h2 database. I am trying to create this project with 'modules' so that we may easily update code as needed. Right now I am trying to create a separate project witch contains our entity definitions, named-queries, and persistence.xml file. I created a JPA project to do this. My question is, how do I export this jar in order to be able to replace it in the future when changes are made? I create a runnable jar which points the the main of the core application, which I am not sure about, and it will run. My problem is when I create the lib folder next to the runnable jar of the core application, my custom 3rd party library containing our entity definition is not there? I am guessing this is because of how I pointed the library to the main of the core application, but as I said I have little experience with this so I am not sure. I cannot seem to find anything helpful out there but I know it must exist. If anyone knows what my issue is or where I should go to read about it, I would be most grateful.
It seems that the problem is with how you package your app? Be aware that a JAR file cannot include other JAR files (at least they are not included in the classpath). Only WAR and EAR may contain another JAR files. If you want to include a JAR nested in another JAR, you must repackage them and merge into a big JAR file, not only put one into another.

Reading a java file from different project

I have two different java projects , and im trying to read one java file in another java file in different project.
eg: i have two projects project1 and project 2. They have packages named package1 and package2 correspondingly. I am trying to read a java file lets say JavaFile2.java which is in package 2 in JavaFile1.java which is in turn in package1 of project1.
I only know that i have to read package2.JavaFile2 , how do i achieve this ?
Need help Badly :(
Thanks
You will have to use either file path relative to project2 or, what seems to be safer option, use absolute file path when opening the file. Overall doing such kind of cross-reference between projects is not a very good idea as you will be tight to the relative location of the two projects.
Iam unable to understand the reason why you want to do so.
However, in the runtime both project1 and project2 will not have .java files available in JVM
having said that, the only option is to include the /src folder in your project archive (jar/war/ear) and writing an adapter which provides the resource from archive is seemingly possible.
You have to add a dependency to the project1 which specifies that the project2 is also on the classpath. Since you haven't specified IDE or anything else, there's nothing I can do right now...
You may try Maven for dependency management
http://www.mkyong.com/tutorials/maven-tutorials/
Well you can use getClass().getProtectionDomain().getCodeSource().getLocation().toExternalForm() to get the location of current project and "navigate" to the other project.
But like said before...I do not understand why you need such cross-referencing.

How to detect duplicate JARs in the classpath?

Does anyone have code to detect duplicate JARs in the classpath?
Background: When there are two versions of the same JAR in the classpath, really strange things can happen. This can even happen when using tools like Maven: Change a dependency and build the WAR without cleaning first. Since target/webapp/WEB-INF/lib wasn't cleaned, the dependency will be in there twice.
Is there a safety-net for this?
JBoss Tattletale might help you with this.
It's a free tool which scans the JAR files used by your project and gives you a report about them.
Amongst its feature are:
Spot if a class is located in multiple JAR files
Spot if the same JAR file is located in multiple locations
Find similar JAR files that have different version numbers
There is a Maven plugin to do just that: maven-duplicate-finder-plugin
[EDIT] If you want to do it in unit tests yourself, use
getClass().getClassLoader().getResources( "com/pany/package/Java.class" )
If this returns more than one URL, you have duplicates on the classpath.
The drawback is that this only works for cases where you had conflicts in the past. On the positive side, it's just a few lines of code (or one line when you write a helper method) and it works on your build server.
System.getProperty("java.class.path"), split it, sort it, look at it with the human eye
:-).
It will not include the classpath derived from manifests inside other jars thou :-(.
Or use http://www.jboss.org/tattletale as one of the posters suggested.
I think the simplest way is to simply trash the target directory first. Hopefully copying all the .jar files in isn't going to be time-consuming.
Otherwise you're going to have to somehow compare sizable files (whether directly, via computed checksum or similar). Which doesn't sound very nice at all.
You can write a simple script to compare the md5 sum of every jar file to every other jar file and deleting duplicates along the way.

Categories

Resources