how can I reflect classes in a springboot jar's BOOT-INF/classes - spring

I need to read a Spring Boot jar and load all the clases on a ClassLoader.
My problem,in spring boot classes are on "/BOOT-INF/classes" directory and not on the root directory.
Anybody knows how i can load this classes in my ClassLoader?
to load the classes inside /BOOT-INF/classes,no the root jar 'org.springframework.*'

As Javassist only looks up classes from the class path and Spring Boot uses its own class loader hierarchy when bundling it in a self-executable. If you want to perform bytecode analysis on springboot user classes then only way is to extract the springboot jar and add each and every class to the classPath so that javassist can perform bytecode analysis on it.

Related

Does jar manifest support `Class-Path`? Why use spring-boot-loader instead?

I know that spring boot packages an executable jar with spring-boot-loader and loads other jars from BOOT-INF/lib as described in this post, using a class named JarLauncher.
After reading this post, I was thinking that Class-Path in manifest can do this, too.
So why does spring boot do so many works to load jars from a customed BOOT-INF/lib, rather than just write simply in META-INF/MANIFEST.MF:
Class-Path: BOOT-INF/lib
The Class-Path manifest approach does not support loading classes from jar files nested within a jar. From the Oracle documentation that you've linked to in your question:
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.
Spring Boot's JarLauncher and the other classes in spring-boot-loader are the custom code that allow classes to be loaded from jars nested within a jar.

How to add class with #resource annotation from a dependancy JAR to spring-boot application

i have two projects one for cache and other to use it. I have added the dependency of cache project as jar in my spring-boot application. but the classes mentioned with #Resouce i am not able to access in my spring boot application. how to resolve it?

Why did Spring Boot 1.4 change its jar layout to locate application classes under BOOT-INF?

(This is primarily a history question. Pivotal recommended that all forum discussions take place on StackOverflow, which is why I am asking it here.)
What are the reasons that the Spring Boot project used to justify moving an application's classes and dependencies from the "top level" of the executable jar format to be underneath BOOT-INF/?
Just trying to guess, it seems that this makes it easy to extract only the application-related classes and jars from the fat jar with a simple java -xf the-jar.jar BOOT-INF/classes command. Was that it? Was there some other reason?
TL;DR
Packaging application classes in the root of the jar required Spring Boot's class loader to use an unconventional delegation model and also caused problems with Java agents.
Detailed explanation
When a jar file is launched with java -jar all of the classes in the root of the jar are on the class path of the system class loader. In a Spring Boot fat jar, this includes the classes for the launcher which is responsible for creating a class loader that can load the application's classes and their dependencies that are nested inside the fat jar.
In Spring Boot 1.3 and earlier, application classes are packaged in the root of a fat jar file. This means that they are on the class path of the system class loader. With a standard, parent first delegation model this would mean that application classes would be loaded by the system class loader rather than Spring Boot's class loader. This is problematic as it's only Spring Boot's class loader that can load the classes from the dependencies that are nested inside the fat jar. The result being that the application cannot load the classes of any of its dependencies.
Spring Boot 1.3 overcame this problem by using an unconventional delegation model for its class loader. It created a new class loader using the URLs from the system class loader but not using the system class loader as a parent – the system class loader's parent was used instead. This meant that Spring Boot's class loader would be used to load the application's classes in the root of the jar and the classes of the application's dependencies in the nested jars.
This approach had some drawbacks. The first was that it made Spring Boot's class loader rather complex. The second was that it broke a number of assumptions that Java agents make with regards to how their classes will be loaded. We worked around a couple of these but it became clear that we were fighting a losing battle.
Spring Boot 1.4 rearranges a fat jar to place application classes in BOOT-INF/classes (it also moves nested jars to BOOT-INF/lib but that has no effect from a class loading perspective). Moving the application classes into BOOT-INF/classes means that they are no longer on the class path of the system class loader. This means that Spring Boot's class loader can be configured to load classes from BOOT-INF/classes and from within the jars in BOOT-INF/lib and use the system class loader as its parent. Java agents can be packaged in the root of the jar from where they'll be loaded by the system class loader as usual.
For further reading you may be interested in the message on the commit that introduced the change and the other issues to which it links.

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

Spring 3 in jar configuration (auto configuration)

I'm looking for some kind of "best practice" informations about Spring jar configuration. I have a web project (war) and I need connect some jar libraries - my jars which contains additional functions. These jars contains Spring services. But when I connect jar, the service class did not work, because Spring don't know about that. So I need to tell Spring about this by “package auto scan” configuration inside my jar.
The final solution must be war project (main functions) and some additional jars which contains other functions. When I add jar into war project, I don't want to change configuration in applicationContext.xml (in war). I want minimal dependency to war project. I was thinking, when if I place applicationContext.xml to META-INF folder in jar it will be auto loaded by Spring, but it is not.
Do you know how can i solve this? May be some kind of “after startup dynamic configuration” :-). thanx
If you are trying to load annotated beans from the jars into your war's Spring context, you can set up a component scan in the war's context xml file to scan the packages in the jars.
If you are trying to load beans defined in XML files from the jars, you can include them using something like this in your war's Spring context xml file:
<import resource="classpath:path/to/config/in/jar/beans-from-jar.xml"/>
You shouldn't need to have your jar know anything about your war this way. You just scan the annotated beans and/or import the config from the jar.

Resources