I have a "plugin like" architecture and I want to create one instance of each class that implements a dedicated interface and put these in a cache. (To have a singleton-ish effect).
The plugins will be provided as jars and put into the app engine war file before the app is uploaded.
I have tried to use the ClassPathScanningCandidateComponentProvider as I'm using spring anyway, but this didn't work. The provider complained that it was not able to find the HttpServletResponse class file while scanning the classpath. I can't get around this, when I add the servlet jar, then I'll get of course problems, because the same jar is also provided by the GAE. If I don't, I'm getting the error above...
So I tried to add a static initialization code, but of course this doesn't work, because the class is initialized when it's instantiated for the first time. (Well I knew that but it was worth a try)
The last chance I currently see is that I create a properties file with all plugin classes when the package is created, but this requires writing of a maven plugin etc. and I'd like to avoid that.
Is there something that I am missing?
OK, I think I'll try to write my own classloader. This way, I could even put the plugins in the datastore and I can detect all the necessary classes etc.
:-)
Related
I'm working on a jax-ws service in Eclipse. At some point, this service opens and uses a couple of XSLT stylesheets.
My question is, can you somehow import and keep these 2 files in the project itself, as you can with a library? For convenience' sake. I basically want my service to work as is, without having to go through the trouble of shipping the xslts along with the service but having to place them in different locations on the server, having to explain to people how and where they must go etc..
On a related note, how come when I make new File("D:\x.xslt");, the service looks for it in "C:\Users\Tudor\Desktop\eclipseJ2EE\eclipse\D:\x.xslt"? As in, *eclipse_path*/*fileName*. I would have understood, if it looked for the file in the root of the apache tomcat server; but not the installDir of eclipse... Anyway, how do I change that behaviour?
You can store the xslt file within your source classpath and load it via the Classloader.
If you are using Spring you can also use the ResourceLoader to load resources.
Its rarely a good idea to use File instances with relative paths directly, since within different server environments the base directory often differs.
Hope this helps.
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.
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
I have a rather complex J2EE app I don't have any documentation for and I am trying to get it to run.
I have gotten the ant build script to compile a EAR file that contains a WAR file, but this application even though I get "successfully deployed" on weblogic console is still not working.
There are many required jars missing from the EAR file, hence I get errors about missing classes on the console log when I deploy the app. Sometimes even after I check a particular class is there I still get the error.
What is a best way to debug and get this application running?
Is there any shortcuts in J2EE/Java to "find all dependencies", apps anybody knows to analyze code and find dependencies or anything like that?
Is there any shortcuts in J2EE/Java to "find all dependencies", apps anybody knows to analyze code and find dependencies or anything like that?
Do you mean a compiler? I'm actually semi serious here (even if the compiler won't give you the name of a missing JAR). Indeed, if you are compiling that application successfully with Ant, then you likely have all dependencies required at compile time (you may need more of them at runtime but, well, you'll need to execute the code to identify them). Maybe you just need to add more of them in the EAR during the packaging. Or maybe you need to add more dependencies at the app server classpath level.
In both case, search engines like jarFinder.com or Docjar.com or Jarhoo.com might help you to identify missing JARs and to solve your ClassNotFoundException or NoClassDefFoundError.
You should actually give readers more details about the missing classes, I'm sure people will be able to give you some hints and point you in the right direction.
I know of no easy way to deal with this. If the application provides an ant task build the EAR then the result should be a self-contained deployable application EAR. It is possible that the EAR requires extra libraries to be added to some class path, without documentation it's really hard to know what.
This phrase is, I guess, at the heart of the problem: "Sometimes even after I check a particular class is there I still get the error." Exactly what do you mean?
You are getting a class not found error but you can see the class in the EAR file? If that's the case then things are really difficult, and may well be some kind of classloader issue. I don't know WebLogic at all, but in WebSphere when deploying an application you have a choice of whether to give precedence to JARs in the EAR or to the same JAR in WebSphere itself. Some Applications demand one or the other setting. If there's anything like that in WebLogic then this may be your problem.
Another possible problem is that the app may depend on infrastructure libraries (Eg. XML parsers) that are supplied by WebLogic, but expects a different version that is supplied with the WebLogic version you are using.
Without documentation that the app is supported on the version of WebLogic you are using, I fear you're fighting a long, hard (or even a losing) battle.
I'd assume you managed to get this application put together and compiled in an IDE, maybe Eclipse. Why not simply put all the Jars that you had available at build time, into the EAR?
If you're having to debug this by trial and error, you can look at the list of missing classes and figure out which jars they belong to by Googling for the class names, or maybe you can find them in your IDE too.
If you have a lot of trouble identifying some classes, post the class names (or the error messages) here and someone should be able to tell you where to find the Jar it belongs in.
If you are able to successfully build and deploy the app, but still getting the errors about missing classes, probably some of the jar classes are called through reflection. You may want to search for reflection API calls in the Project through your IDE.
These calls may be something like,
"Class cls = Class.forName(..); cls.newInstance()."
Sometimes even after I check a
particular class is there I still get
the error.
This may be a deployment issue. check the classpath. Some of the jars may be missing from the Classpath.
Is there any shortcuts in J2EE/Java to
"find all dependencies", apps anybody
knows to analyze code and find
dependencies or anything like that?
I'd start by having another go at getting documentation ... or help ... from the original developers, if you can find them. [IMO, people who develop / provide software without any documentation deserve to be bugged incessantly by people asking silly questions.] But I guess you've already tried that.
Then there are the jarfinder.com and other services as mentioned in another answer. (New to me!)
If that fails, I'd try doing a Google search on the FQNs. The chances are that if the missing classes are part of a commonly used library you will hit the Javadocs ... or a posting from someone else with a similar problem to yours.
If the "Google it" approach fails, use the clues in the package naming for the missing classes to try and find where they come from. If they follow the Sun recommendations, the names should map to a company or (real or pseudo-) organization that you can locate by a web search.
I'd like to implement a dynamic plugin feature in a Java application. Ideally:
The application would define an interface Plugin with a method like getCapabilities().
A plugin would be a JAR pluginX.jar containing a class PluginXImpl implementing Plugin (and maybe some others).
The user would put pluginX.jar in a special directory or set a configuration parameter pointing to it. The user should not necessarily have to include pluginX.jar in their classpath.
The application would find PluginXImpl (maybe via the JAR manifest, maybe by reflection) and add it to a registry.
The client could get an instance of PluginXImpl, e.g., by invoking a method like getPluginWithCapabilities("X"). The user should not necessarily have to know the name of the plugin.
I've got a sense I should be able to do this with peaberry, but I can't make any sense of the documentation. I've invested some time in learning Guice, so my preferred answer would not be "use Spring Dynamic Modules."
Can anybody give me a simple idea of how to go about doing this using Guice/peaberry, OSGi, or just plain Java?
This is actually quite easy using plain Java means:
Since you don't want the user to configure the classpath before starting the application, I would first create a URLClassLoader with an array of URLs to the files in your plugin directory. Use File.listFiles to find all plugin jars and then File.toURI().toURL() to get a URL to each file. You should pass the system classloader (ClassLoader.getSystemClassLoader()) as a parent to your URLClassLoader.
If the plugin jars contain a configuration file in META-INF/services as described in the API documentation for java.util.ServiceLoader, you can now use ServiceLoader.load(Plugin.class, myUrlClassLoader) to obatin a service loader for your Plugin interface and call iterator() on it to get instances of all configured Plugin implementations.
You still have to provide your own wrapper around this to filter plugin capabilites, but that shouldn't be too much trouble, I suppose.
OSGI would be fine if you want to replace the plugins during runtime i.g. for bugfixes in a 24/7 environment. I played a while with OSGI but it took too much time, because it wasn't a requirement, and you need a plan b if you remove a bundle.
My humble solution then was, providing a properties files with the class names of plugin descriptor classes and let the server call them to register (including quering their capabilities).
This is obvious suboptimal but I can't wait to read the accepted answer.
Any chance you can leverage the Service Provider Interface?
The best way to implement plug-ins with Guice is with Multibindings. The linked page goes into detail on how to use multibindings to host plugins.
Apologize if you know this, but check out the forName method of Class. It is used at least in JDBC to dynamically load the DBMS-specific driver classes runtime by class name.
Then I guess it would not be difficult to enumerate all class/jar files in a directory, load each of them, and define an interface for a static method getCapabilities() (or any name you choose) that returns their capabilities/description in whatever terms and format that makes sense for your system.