We have a new project which we're writing using Spring Boot in which we're using Log4j2 for our logging.
The problem is that we need to use an legacy library, which we own but we can't change; several other systems use it and we can't increase our scope by changing all of them.
When our project runs, it logs just fine using Log4j2, but when we make calls to the legacy library, it makes Log4j calls which throw exceptions.
Is there a way to, in our new application which uses log4j2, handle the old log4j calls?
Update
Our legacy JAR contains several JARs in an internal lib folder including:
log4j-1.2.6.jar
Our project is a Spring Boot project and we've included the dependency:
org.springframework.boot:spring-boot-starter-log4j2
The log4j JARS that I see on the projects classpath are:
spring-boot-starter-log4j2--1.5.9.RELEASE.jar
log4j-slf4-impl-2.7.jar
log4j-api-2.7.jar
log4j-core-2.7.jar
Have you tried the log4j-1.2-api adapter? Use this together with the log4j-api and log4j-core dependencies. The adapter lets applications use the Log4j 1.2 API, but routes these calls to the log4j2 implementation. See the which jars question in the FAQ.
If the application uses internal Log4j 1.2 classes this may not work but for plain logging it’s a drop-in replacement of the log4j-1.2.x jar.
Note that the legacy log4j-1.2.x jar should be removed from the classpath for this to work.
Update: if the legacy jar contains the Log4j 1.2.x jar and this causes the Log4j 1.2.x jar to be added to the classpath, the results are undefined.
I believe you have little choice but to create a custom version of this legacy jar without the Log4j 1.2.x jar. Other systems in your organization can continue to use the original legacy jar with the embedded Log4j 1.2.x jar, until they also want to migrate to Log4j2.
Your new version of the legacy jar (without embedded Log4j 1.2.x jar) may become the pathway to migrating to Log4j2 for all other systems in your organization.
Related
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?
I have a spring-boot application in which I loaded all the necessary (or so I believe) dependencies to run without using spring-boot initializer or the spring-boot gradle plug-in. These tools are not available for me at my work. I can run the application through intellij without issues, but when attempting to run a fat jar, I am met with
No auto configuration classes found in META-INF/spring.factories.
Now the spring.factory files ARE located inside the fat jar (there are multiples of them) and they are inside the meta-inf directory.
Spring boot has so much automated functionality, I am not sure where to begin. There are a lot of similar posts and everyone just tells people to use the spring-boot gradle plugin bootJar task but as I said these are not available to me. I need to get it running without those tools,
if anyone has insight into what the issue may be or how to resolve it, any help is appreciated. I will try to add more details later.
I am using spring-boot v. 2.1.1 and spring 5.1.4
Spring boot starter project provides extensive set of functionalities auto configured. But for our application we want to have only a subset of functionality. May be only one feature out of the spring boot starter project. So is it advised to have custom starter project on top of spring boot provided starter project to mask some of the features or write new starter project directly from lower level libraries?
Spring boot starter project provides extensive set of functionalities
auto configured
There are two separate concerns you are talking about.
I think the auto configured part is something which is Spring boot's opinionated way of configuring. As an example if in classpath it finds a in-memory database library ( like H2) it automatically creates a datasource (pointing to embedded in-memory database) which is available for autowiring without you writing the configuration in a Java config class. Of course you can create you own datasource of choice by including appropriate driver jar for that database. Similarly lots of other configurations are done by default by classpath scanning and availability of certain jars and classes.
The second part - is more of a dependency issue in general. Say you want to use web mvc part in Spring boot. This will require a consistent set of dependencies and transitive dependencies as well. Rather than finding and declaring the dependency in your build tool of choice ( maven, gradle etc) it has created the concept of starter projects where you simply mention the parent and all the right dependencies would be pulled on. This gives a great way to correctly lock your dependencies. However if you want to include any different version than what is provided by boot starter ( provided there is no compatibility issues with those different versions) you can still add explicitly in your build tool. For e.g., maven will by default include the highest version of a particular dependency among all available via transitive dependencies when it resolves dependency for an artifact.
I am making war packaging of my spring boot. made spring boot starter tomcat as provided, removed spring boot maven plugin.
But I still see tomcat jdbc and tomcat juli, to name a few (even junit, but it could be from other custom dependencies, so discounting this for this question). I am using logback, but I see log4j over slf4j from starter web.
Can I ask, how to skip unwanted jars and keep my package nice and tidy
Maven has the concept of "scope" for dependencies. You probably know the scope test which is used for unit test dependencies which should not go into the final product. Use this scope for junit.
What you need is the scope provided for the Tomcat dependencies. This tells Maven: "Don't include it; when the code is run, someone else will make sure this dependency is on the classpath".
The dependency log4j-over-slf4j is necessary when one of your dependencies still uses log4j to log. log4j-over-slf4j contains the code to redirect those calls to logback.
Now you will face the case where you can't change the scope because it's in a POM of someone else.
The correct solution here is to define the dependency with the correct scope (and version) in a dependencyManagement element in your POM. This definition will be used when any POM asks for this group+artifactId. So even when some deep dependency of Spring Boot pulls that in, your WAR will be build with the version and scope from the dependencyManagement element.
See also:
Dependency Scopes
Dependency Management
I am trying to integrate Spring RESTful service in my project which already uses log4j. Log4j is conflicting with commonslogging and not initializing the service. I am using commons logging to compile spring jar.
If your using Maven try
<scope> provided</scope> for log4j transitive dependencies.
Issue has been resolved by including log4j.xml in my classes folder.
With all research on this topic, I come to know that jar conflict issue is with Webspehere not with Tomcat.