Dynamic loading of spring bean from jar along with dependent beans - spring

I am running a spring application.
My requirement is user will be placing a plugin jar file at run time at designated lib folder location.
This plugin jar file will have spring application context file as well. I want to load this jar, means all the classes - spring beans
and all its dependent beans/components(this is important), from this jar file at run time.
I do not want to create new/child application context and want to use the existing spring bean context loaded at application start up.
I reffered to few other similar threads/questions on SO and could resolve the issue of dynamically loading of spring beans.
But i am not able to resolve issue of loading all the dependent beans for the spring beans.
Could you please provide any pointers/hints to dynamically load all the dependent beans of spring bean(which is also)loaded at run time?
Thanks in advance,
Picku

If you want to be able to load the plugin after startup you are not going to get away with not creating another application context as a child.
I'd suggest you do exactly this and then create some hooks in parent context whereby your plugin will integrate itself.
The alternative is to include that plugin.jar in the main classpath and then restart the application to include the plugin.

Related

Spring Boot JarFileSystem for wrapped JARs

I've got a Spring Boot application packaged as an Uber JAR. One of the wrapped JARs has logic within it to utilize a Java FileSystem for walking a resource tree that is embedded in that particular JAR file.
Unfortunately, this statement appears to be true:
Now opening jar files isn't a big deal. Esp with the introduction of the JarFileSystem. However Spring Boot includes jar files inside their jars. There is currently no support for that. You can't create a JarFileSystem inside a JarFileSystem.
With that being said, Spring Boot has a fair amount of handling surrounding it's wrapped JARs:
JarURLConnection
Everything else under org/springframework/boot/loader/jar
However, there doesn't appear to be any mechanism for registering Spring Boot's approach as a FileSystemProvider...
org.springframework.boot.loader.LaunchedURLClassLoader unable to load 3rd party FileSystemProvider implementation from spring boot executable JAR seemed like a similar problem, but didn't appear to be directly related.
Has anyone had any luck creating a FileSystem for one of Spring Boot's wrapped JARs?

Prevent SpringBoot from creating an EmbeddedServletContainer

I'm trying to convert an existing spring application into a spring boot application. this application is not a web application but somewhere deep in it's maven dependencies hierarchy it includes a spring-web jar and therefore spring-boot tries to autoconfigure a WebEnvironment and in turn complains about not finding an EmbeddedServletContainerFactory. But this is intended as I'm using spring-boot-starter instead of spring-boot-starter-web.
My questing is: how can I prevent spring-boot from autodiscovering web specific items in the classpath? I already tried something like
#EnableAutoConfiguration(exclude = { EmbeddedServletContainerAutoConfiguration.class })
but it doesn't seem to work. Debugging the startup process I see that it runs into a method called deduceWebEnvironment() which is called unconditionally. This method returns true as soon as the following classes are on the classpath:
javax.servlet.Servlet, org.springframework.web.context.ConfigurableWebApplicationContext
But again, even this classes exist in the cp, I don't want to startup a web-application.
Try new SpringApplicationBuilder(YourApp.class).setWebEnvironment(false).run(args) You can also disable the web mode via configuration in application.properties
spring.main.web-environment=false
See the documentation

Classloader issue on Mule server

I am running my application on mule server. Mule server has there own sets of jars and my application that is running on mule server also has few jars. While working on Spring batch I found that JettisonMappedXmlDriver class exists in my application xstream jar as well as mule server jar as well. This class internally refer MappedXMLOutputFactory class that is in jettision jar which is also in my application but some how I am getting classnotfound error for MappedXMLOutputFactory class. This looks like class-loader issue.
If I add jettision jar in mule server then everything work fine but, I can't add this jar on my production environment. Can some body tell me how do I force to load the class from my application jettision jar file. It looks weird to me as classloader should have load MappedXMLOutputFactory class from jettision jar that is in my application folder like it is doing for other classes.
Please let me know if anybody found such issue.
The Mule application classloader is configurable: http://www.mulesoft.org/documentation/display/current/Classloader+Control+in+Mule
So just configure your application's classloader to first look at the JARs it embeds in /lib before deferring to the Mule System classloader.
You will encounter this issue if you have multiple versions of the same class in differnet jars, albeit with different method signatures. The ClassNotFound Error is usually not the only exception that occurs, you will often see another one before that, typically a "NoSuchMethodException" which forces class loader to unload the offending class.
I would suggest using maven or gradle to assemble your application and then use the dependency:tree target to query version conflicts.

Spring with maven-shade-plugin

I am trying to use to versions of spring in the same application: the first one is a webapp with spring 2.6 and the second it a jar client, with spring 4.0.2. The client communicates with another application and will be a dependency for the webapp. The problem is that the classloader will just load one time the common classes from spring and it will certainly fail.
I tried to use ElasticSearch aproach of using shaded dependencies(maven shade plugin) and relocate spring from the client to a different package (from org.springframework to my.springframework) and the uber jar seems to be constructed fine.
The issue is that Spring is based on spring.schemas and spring.handlers for validating xml config files and loads this files from classpath (META-INF folder and this paths are hardcoded in Spring code - e.q. PluggableSchemaResolver). I modified this files to point from org.srpingframework to my.springframework.
At runtime it seems that the classloader reads these files from the webapp, which has this files but with the real spring path and the exception is something like
org.realsearch.springframework.beans.FatalBeanException: Class [org.springframework.context.config.ContextNamespaceHandler] for namespace [http://www.springframework.org/schema/context] does not implement the [my.springframework.beans.factory.xml.NamespaceHandler] interface.
To me it seems that is impossible to achieve what I am trying (use tho spring versions in the same application with one of them relocated). Any ideas here? Am I wright?:d

Cloning Spring Application Context in OSGi bundle

I have a Spring-enabled OSGi bundle. I'd like this bundle to export a factory-type OSGi service which client software can use to create multiple instances of the application context defined in this bundle.
By default the Spring DM library bundles will automatically scan and create an instance of an application context from any Spring XML configuration found under "META_INF/spring". To avoid this I moved the Spring XML configuration files under a different folder and then tried creating the application context programmatically on demand from the factory class. Unfortunately I ran into issues with Spring schema files not being available on the bundle classpath. I really don't want to embed the required Spring jars within my bundle just to get access to those schemas.
Is there a simpler way to clone Spring application contexts under an OSGi environment?
I do not understand your problem in detail but if you just want to load the application-context from a different location than META-INF/spring you can define this in the MANIFEST.MF file using 'Spring-Context', e.g. for files in the root folder
Spring-Context: /application-context-core.xml,/application-context-osgi.xml
See the documentation for further information.

Resources