we have some dependent/common jars of the plugin which we are currently placing in .lib of ContentNavigator application and referring the same in build.xml of ContentNavigator. while we placed the jars in local and tried to give the local path in build.xml it didn't worked out.Can anyone suggest what is the recommended way of doing it?
I've applied the following approaches:
Embed/extract all the content(.class files) of the dependency-jars within the navigator plugin. While the upside is that you have a nice bundle containing all your dependency-classes, it might cause some problems with signed jar's. Or on files that are duplicate amongst your dependencies.
Make use of the "Shared Library" concept. You basically "attach" jar's to the classloader of your server/JVM, Application(ear) or module(war). In your case you would probably attach the shared-library to the navigator.ear, allowing all plugins to access the dependencies you register as a sharedlibrary. One huge downside is (in my experience) that you need to reboot websphere every time you update one of the library-jars.
A third option is to move the functionality out of your ICN Plugin, and let another EAR/EJB do the work (and reference to it from the plugin using a jndi lookup).
I personally prefer option 3 because it's the cleanest way to bundle your functionality&dependencies in an EAR. But option 2 will be a good call when libraries are truely common and won't be updated often.
p.s. In your question you mention the build aspect of your software as well (e.g. "how to correctly reference the dependencies"). You might want to look into the concepts of "dependency management" (using Ant, IVY is a good choice, but i would suggest moving to Maven, or Gradle)
Related
I have many small Scala applications and I would like a central place to manage versions of common dependencies.
I know I can set up a Build.scala file and define multiple projects. I used to have that, but not all of these applications are related in that sense. They just happen to share a common software architecture.
How do I achieve this with SBT? Currently I'm managing multiple .sbt files that I batch update (like dependencies.sbt, common.sbt etc.).
My initial approach was to start writing a plugin, but I got stumped along the way with getting dependencies working within the plugin.
I wanted to collect plugin settings and build settings. But I never got one plugin to depend on a set of other plugins.
Anyone tried this before, how do I manage central application profiles (both plugins and settings)?
Do you mean different applications? You can then just put your settings into global.sbt. You can look for more detailed description here
I have imported, from git, a large build that has a bunch of 3rd party dependencies. The annoying thing is, that there is no javadoc attached for any of the 3rd party apis! Is there any way to automatically add javadoc to an Eclipse project's libraries (all referenced libraries, not just one)? It would take way too long to add all the javadoc one by one.
Although I'm using gradle to build, it uses maven under the hood and generates a pom. I would figure that there's a way to generate javadoc from all referenced libraries in the pom, rather than have to add them each one at a time via the eclipse build path.
My instinct says there's not simply by asking 'how would we know remotely where the javadoc is kept', but I have to ask just in case someone knows a way. I'd hate to add all the javadoc manually and figure out there's a faster way.
Have you seen this answer? Maven – Always download sources and javadocs
If that doesn't work, then probably the sources are unavailable for the dependencies you added (and you'll have to do it manually, as far as I know).
Considering that I am developing an end-user software program (as an uberjar) I am wondering what my options are to make it possible for the user to download a plugin and load that during runtime.
The plugin(s) should come compiled and without source code, so sth. like load is not an option.
What existing libraries (or ways of Java...?) exist to build this on?
EDIT: If you are not sure I would also be satisfied with a way that costs a reboot/-start of the main-program. However, what is important is that the source-code won't be included in any JAR file (neither main application nor plugin-jars, see :omit-source of Leiningen documentation).
To add a jar during runtime, use pomegranate which lets you add a .jar file to the classpath. Plugins of your software should be regular Clojure libs that follow certain conventions that you need to establish:
Make them provide (e. g. in an edn) a symbol to an object implementing a constructor/destructor mechanism such as the Lifecycle protocol in Stuart Sierras component library. In runtime, require and resolve that symbol, start the resulting object and hand it over to rest your programs plugin coordination facilities.
Provide a public API in your program that allows the plugins to interact with it in ways that you coordinate asynchronously e. g. with clojure.core.async (don't let one plugin block the entire program).
Make sure that the plugins have a coordinated way to expose their functionality to each other only if they desire so to enable a high degree of modularity among your plugins. Make sure that your plugin loader is capable of detecting dependencies among plugins and is capable of loading and unloading them in the right order.
I've not tried it myself, but you should in theory be able to get OSGi to work with Clojure.
There's a Clojure / OSGi integration library here:
https://github.com/aav/clojure.osgi
If I were to attempt to role my own solution, I would try using tools.namespace to load and unload plugins. I'm not entirely sure it will work, but it's certainly in the right direction. I think one key piece is that the plugin jars will have to be "installed" in a location that's already on the classpath.
Again, this is only the start of one possible solution. I haven't tried doing this.
I think (see below) that I would like to structure a Clojure project as multiple modules, with ordered dependencies - just like Maven lets me do with multi-modules projects.
But I can't see how to do this with Leiningen - all I can see is the checkouts fix described in the FAQ which doesn't seem to be as powerful.
Will lein do this? Should I be using Gradle instead? Or is this kind of thing not needed?
Some more context: I am wondering how to architect a modular application that supports plugins (which I imagine means jars dumped on the classpath). And am wondering to what extent I can structure that as a core + plugins (I am thinking I should be able to do something with Clojure's dynamic code loading and not have to go with Java/OSGi). So I guess the driving motivation for a single project comes from wanting some way of packaging everything (the core + default plugins) as a single blob that is easy for the end user, but which can also be divided up (and which is built and tested in fragments, testing the logical independence of each module). More general advice about this is welcome
Update
A possible solution that wasn't mentioned below is using a Maven plugin - I assume that supports everything Maven does, but compiles Clojure, so will work with nested modules, etc.
First, it does not seem like Leiningen supports a module hierarchy like Maven does. The checkouts are the next closest thing it has. It should be sufficient though to develop a modular application in Clojure though.
For the project structure, I would have an API project, a "core" project, the plugins themselves, and a separate packaging project. The core and the plugins should only depend on the API. Which build tool you use to create the packaging project is up to you. Gradle would probably be more effective at handling the packaging, however having the "checkout" functionality Leiningen offers could make development of the system as a whole easier.
I would take a look at the code for Leiningen and Noir to figure out how to effectively handle this.
For dynamically loading the plugins, I would start with looking how Noir handles it in two of their files:
server.clj has namespace loading for all files under a particular namespace. Under the hood it uses tools.namespace, but you can easily see how it's used to require every namespace under a particular base. This is how Leiningen handles custom tasks as well - the base definition for the task should be in the leiningen.$task namespace.
core.clj has what I would use for plugin registration. In summary, use a map under an atom and add plugins to that map. I would advice wrapping the registration with a macro to keep your code cleaner.
What I listed above should be sufficient if you don't need to handle adding plugins at run time. If you don't have every plugin on the classpath during start-up, I would recommend utilizing pomegranite to add entries to the classpath. You can see an example in classpath.clj.
There are a lot of similar questions, but none for this specifically. I have a Netbeans project with a bunch of packages. Only one has Main. I'd like to be able to create a .jar from just one of the packages (and all the classes it contains, of course), which doesn't have main.
Is this feasible without having to put that package in another project or without having to screw around with build.xml? If the latter, any easy way or good rtfm links?
The point is i'm developing part of an application for college, each group member is developing a module of sorts. If each could provide their .jar the main project can just include jars and use them. I'm guessing all the mains in the jars wouldn't really hurt? But still...
You can use the project properties to customize your project's jar file content. This screenshot shows what it looks like for a Java Class Library project.