Skip to content

Elasticsearch starter forces use of Log4j2, breaking logging in apps that try to use Logback #10847

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
staleks opened this issue Oct 31, 2017 · 15 comments
Labels
type: bug A general bug
Milestone

Comments

@staleks
Copy link

staleks commented Oct 31, 2017

I'm trying to run spring-boot-starter-data-elasticsearch in latest Milestone 2.0.0.M5.

I've used project template generated from start.spring.io.
Here is the GitHub repo url: https://github.com/staleks/spring-boot-2.0.M5-ES

Run

  1. $ ./gradlew clean build
  2. $ ./gradlew bootRun

stale the process of loading application context.
Please check the attached image: https://github.com/staleks/spring-boot-2.0.M5-ES/blob/master/images/staled-bootRun-process.png

On the other hand, if I switch back to 1.5.8.RELEASE version
(GitHub repo url: https://github.com/staleks/spring-boot-1.5.8-ES)

Run

  1. $ ./gradlew clean build
  2. $ ./gradlew bootRun

application context is loaded, and web application is started.
Please check the attached image: https://github.com/staleks/spring-boot-1.5.8-ES/blob/master/images/bootRun-process.png

Can someone please verify this?

Thank You

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 31, 2017
@wilkinsona
Copy link
Member

Thanks for the sample. The application starts successfully, it's just some logging that's lost. That appears to be due to the fact that you have both Logback and Log4j2 on the classpath. Things work as expected if you exclude Log4j2:

compile('org.springframework.boot:spring-boot-starter-data-elasticsearch') {
    exclude group: 'org.apache.logging.log4j'
}

I'm not sure why Spring Data Elasticsearch pulls in all of Log4j2 rather than just a logging API. That should either be changed in Spring Data Elasticsearch or we should consider adding some exclusions in our starter.

@olivergierke @mp911de Can you please advise?

@wilkinsona wilkinsona added priority: normal type: bug A general bug status: blocked An issue that's blocked on an external project change and removed status: waiting-for-triage An issue we've not yet triaged labels Oct 31, 2017
@odrotbohm
Copy link
Member

That's a bug in the POM. Feel free to exclude in the starter for the upcoming milestone but we're gonna get this fixed with the next bugfix release for Kay.

@staleks
Copy link
Author

staleks commented Oct 31, 2017

Confirmed!
If log4j is excluded from starter-data-es then application context is loaded correctly.

Thank You for clarification and help.

Note: I'm trying to use new spring-data-elasticsearch v3.0.0.RELEASE in order to connect to ES 5.x.
Therefore I'm experimenting with spring-boot-starter 2.0.0.M5.

@staleks
Copy link
Author

staleks commented Oct 31, 2017

"Two cents" more on this topic :), as it seams not solved just by exclusion.

Try to add ElasticSearch Configuration class (JavaConfig), e.g.

@Configuration
public class ESConfig {
	
	@Bean
	public Client client() throws UnknownHostException {
		TransportClient esClient = new PreBuiltTransportClient(Settings.EMPTY);
		esClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9200));
		return esClient;
	}
	
	public ElasticsearchOperations esTemplate() throws UnknownHostException {
		return new ElasticsearchTemplate(client());
	}
	
}

Now, starting application will "complain" about missing log4j.

Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.Level
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_131]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_131]
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) ~[na:1.8.0_131]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_131]
	... 45 common frames omitted

In order to help you debug this, please checkout GitRepo:
https://github.com/staleks/spring-boot-2.0.M5-ES and switch to development branch.

Note: org.apache.logging.log4j.Logger introduced in
org.elasticsearch.common.component.AbstractComponent of elasticsearch-5.5.3.jar

@philwebb
Copy link
Member

@staleks Can you post the full stack trace please.

@staleks
Copy link
Author

staleks commented Nov 1, 2017

@odrotbohm
Copy link
Member

I guess that's the reason, the Log4j dependencies made it into the compile scope of Spring Data ES in the first place. I tried to remove the dependencies completely as we pull in Logback in the Spring Data builds during tests anyway but that causes the tests to fail with a similar exception. It looks like ES doesn't properly run without Log4j being used.

@wilkinsona
Copy link
Member

wilkinsona commented Nov 1, 2017

I believe that can be avoided with a runtime dependency on org.apache.logging.log4j:log4j-to-slf4j.

@staleks For some reason that module is not part of Log4j2's bom (so Boot doesn't currently manage its version). However, you can align its version with the version of the log4j-api module (which Boot does manage) like this:

runtime("org.apache.logging.log4j:log4j-to-slf4j:${dependencyManagement.managedVersions['org.apache.logging.log4j:log4j-api']}")

In summary, I think the long term fix for this is for Spring Data Elasticsearch to exclude any Log4j2 implementation dependencies and pull in org.apache.logging.log4j:log4j-to-slf4j instead. As a temporary measure for Boot M6, we can create the same arrangement by updating spring-boot-starter-data-elasticsearch.

@wilkinsona wilkinsona changed the title Elasticsearch staled bootRun Elasticsearch starter forces use of Log4j2, breaking logging in apps that try to use Logback Nov 1, 2017
@wilkinsona wilkinsona removed the status: blocked An issue that's blocked on an external project change label Nov 1, 2017
@wilkinsona wilkinsona added this to the 2.0.0.M6 milestone Nov 1, 2017
@wilkinsona
Copy link
Member

I've opened LOG4J2-2093 to see if log4j-to-slf4j could be added to Log4j 2's bom.

@odrotbohm
Copy link
Member

Thanks, Andy. I’ll proceed as suggested and ping you once the fix is available.

@spencergibb
Copy link
Member

@wilkinsona This change caused a test to fail in spring-cloud-gateway. See https://jenkins.spring.io/blue/organizations/jenkins/spring-cloud-gateway-2.0.x-ci/detail/spring-cloud-gateway-2.0.x-ci/1019/pipeline

Adding the following exclusion to the pom fixed the error. Seems a bit bizarre to me:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.apache.logging.log4j</groupId>
					<artifactId>log4j-to-slf4j</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

@wilkinsona
Copy link
Member

It appears that the test failures are due to a bug in ModifiedClassPathRunner which is causing Provider to be loaded by two different class loaders. Let me know if fixing Spring Cloud’s copy of the runner doesn’t help and we can take another look.

@spencergibb
Copy link
Member

Adding changes you made to the boot version (excluding log4j jars) fixed the problem.

@wilkinsona
Copy link
Member

Aah, I'd forgotten I'd had to do that. Sorry. Could have saved us all some cycles if my memory was a bit better…

@odrotbohm
Copy link
Member

The reductions of the scope of the log4j dependencies for Spring Data Elasticsearch have now been applied to the Lovelace and Kay release train branches. Snapshots should be available shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

6 participants