elastic / elasticsearch

Free and Open, Distributed, RESTful Search Engine
https://www.elastic.co/products/elasticsearch
Other
69.52k stars 24.6k forks source link

Can't use Java client due to NoClassDefFoundError: org/apache/log4j/Priority #19415

Closed fakeh closed 8 years ago

fakeh commented 8 years ago

I had to add these dependencies to resolve:


        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.5.11</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>

Elasticsearch version: 5.0.0-alpha4

JVM version: java version "1.8.0_60" Java(TM) SE Runtime Environment (build 1.8.0_60-b27) Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

OS version: OSX 10.11.5

Description of the problem including expected versus actual behavior: Can't use Java client, due to NoDefFound from ESLogger.

Steps to reproduce:

  1. Create Maven project
  2. Depend on
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>5.0.0-alpha4</version>
        </dependency>
  1. Try to make a client:
    private Client client = TransportClient.builder().build().addTransportAddress(
            new InetSocketTransportAddress(new InetSocketAddress("localhost", 9300)));

Provide logs (if relevant):

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Priority
    at org.elasticsearch.common.logging.ESLoggerFactory.getLogger(ESLoggerFactory.java:42)
    at org.elasticsearch.common.logging.ESLoggerFactory.getLogger(ESLoggerFactory.java:46)
    at org.elasticsearch.common.logging.Loggers.getLogger(Loggers.java:123)
    at org.elasticsearch.common.settings.Setting.<clinit>(Setting.java:110)
    at org.elasticsearch.common.logging.ESLoggerFactory.<clinit>(ESLoggerFactory.java:33)
    at org.elasticsearch.common.logging.Loggers.getLogger(Loggers.java:119)
    at org.elasticsearch.transport.netty.NettyInternalESLoggerFactory.newInstance(NettyInternalESLoggerFactory.java:33)
    at org.elasticsearch.common.netty.NettyUtils$1.newInstance(NettyUtils.java:91)
    at org.jboss.netty.logging.InternalLoggerFactory.getInstance(InternalLoggerFactory.java:67)
    at org.jboss.netty.logging.InternalLoggerFactory.getInstance(InternalLoggerFactory.java:60)
    at org.jboss.netty.util.ThreadRenamingRunnable.<clinit>(ThreadRenamingRunnable.java:32)
    at org.elasticsearch.common.netty.NettyUtils.<clinit>(NettyUtils.java:95)
    at org.elasticsearch.transport.netty.NettyTransport.<clinit>(NettyTransport.java:145)
    at org.elasticsearch.client.transport.TransportClient$Builder.newPluginService(TransportClient.java:108)
    at org.elasticsearch.client.transport.TransportClient$Builder.build(TransportClient.java:120)
    at edge.model.TestElastic.<clinit>(TestElastic.java:10)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Priority
    at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 16 more
clintongormley commented 8 years ago

Hi @fakeh

Thanks for trying out the alpha. What you report is correct, and it is listed in the breaking changes: https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_java_api_changes.html#_elasticsearch_will_no_longer_detect_logging_implementations

fakeh commented 8 years ago

Thanks for the swift response. If the libraries are required, why not pull in the dependencies transitively?

clintongormley commented 8 years ago

We don't use transitive dependencies at all.

cooniur commented 7 years ago

Hi @clintongormley , is there a doc explaining the reason why Elasticsearch 5.0 Java SDK uses Log4j2 instead of Slf4j that is IMHO much less intrusive?

nik9000 commented 7 years ago

Hi @clintongormley , is there a doc explaining the reason why Elasticsearch 5.0 Java SDK uses Log4j2 instead of Slf4j that is IMHO much less intrusive?

Because Elasticsearch is a server we don't feel the need to talk to a logging abstraction layer. We'd have used it if we liked the API better but we don't.

The transport client is a problem in this case, because it uses Elasticsearch's code base as though it were a library. This isn't a thing we can live with in the long term because it boxes us in in the choices we can make. So the elasticsearch java REST client is becoming a thing, though it honestly is too low level for Java developers to really enjoy using it at this point.

davidbilge commented 7 years ago

Unfortunately, the Elasticsearch Java Client is not a server. If we want to use the API Jar in one of our applications, this choice forces us to use log4j.

Unfortunately, there does not seem to be a log4j2-over-slf4j library, the log4j-over-slf4j library only seems to work with log4j 1.x.

Edit: I think I found a bridge that allows to continue using logback, see http://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-to-slf4j/2.7

nik9000 commented 7 years ago

Unfortunately, the Elasticsearch Java Client is not a server. If we want to use the API Jar in one of our applications, this choice forces us to use log4j.

That is the problem with transport client. It is the server. The same bits. You don't want it to be the server and neither do we. Thus the REST client which is, sadly, far from ready yet.

I think I found a bridge that allows to continue using logback, see http://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-to-slf4j/2.7

Yeah, I didn't read to your edit and was about to post https://logging.apache.org/log4j/2.0/log4j-to-slf4j/index.html which looks like the same link.

nik9000 commented 7 years ago

Er, looks like it is talking about the same artifact, rather.

dadoonet commented 7 years ago

@davidbilge May be in the meantime you can shade elasticsearch server when it is used with the transport client? In that case, this article may help: https://www.elastic.co/blog/to-shade-or-not-to-shade

davidbilge commented 7 years ago

@dadoonet Thanks for the idea, I will look into that. For now, I'm perfectly fine using the log4j-to-slf4j bridge.

dadoonet commented 7 years ago

@davidbilge I wonder if it is worth adding that in the doc. I mean in the Transport Client java documentation. Would you like to describe what you did to help other users? Like what was made with this specific page? https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/_deploying_in_jboss_eap6_module.html

davidbilge commented 7 years ago

Sure thing. The dependencies in my pom.xml basically look like this:

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>5.0.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-to-slf4j</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.7</version>
</dependency>

That solves the missing java.lang.ClassNotFoundException if you use a logger that implements slf4j (like logback does).

mvmn commented 7 years ago

That is the problem with transport client. It is the server

Client is not server. You can't say "client is server", this is absurd, it makes no sense. Client is client, server is server, period.

I get what you mean though - client reuses some classes from server.

it uses Elasticsearch's code base as though it were a library

This is clear.

But, when you actually spell it this way, e.g. correct way, then the fix becomes obvious - decouple shared classes from server and put it into separate library, not dependent on Log4J. Trivial.

jasontedor commented 7 years ago

Client is not server. You can't say "client is server", this is absurd, it makes no sense. Client is client, server is server, period.

But, when you actually spell it this way, e.g. correct way

These establish an adversarial relationship rather than a collaborative one. We strongly prefer the latter, and this matters to us a lot.

I get what you mean though - client reuses some classes from server.

It can't be both "absurd" and "make no sense", and you get what he means. You left off a key sentence that elucidates exactly what he meant:

It is the server. The same bits.

The two sentences go together.

then the fix becomes obvious - decouple shared classes from server and put it into separate library [...] Trivial.

The fix is obvious, but obvious is not the same as trivial. There is a lot of entanglement. We know the fix, we want to do the fix, but on this subject, for the client effort, we value pragmatism over idealism (see previous comments on this very subject).

mvmn commented 7 years ago

It can't be both "absurd" and "make no sense"

Ok. Pick the one you like more.

The two sentences go together.

You do realize the implications of stating that any two codebases that share common classes are the same ("client and server share classes, therefore client is server")? Let's consider an example: Tomcat uses java util logging and Weblogic uses java util logging - therefore Tomcat is Weblogic (but not vice versa)? Absurd or makes no sense - pick one you like.

The fix is obvious, but obvious is not the same as trivial

You're picking on words instead of figuring out the meaning behind words. Speaking of adversarial - let's not pick on words and start a demagogue contest, shall we?

It would be interesting to know what kind of entanglement prevents one from simply moving shared classes into shared library. The information on the problem - not opinions of the comments on the problem - that would be collaborative instead of adversarial.

clintongormley commented 7 years ago

Well done @mvmn - way to kill a thread...

mvmn commented 7 years ago

The information on the problem - not opinions of the comments on the problem - that would be collaborative instead of adversarial.

imod commented 7 years ago

The above dependencies do not help if I run elasticsearch (v5.1.2) embedded (we do this for testing)...

as soon as I create an index, e.g.

        CreateIndexRequest createIndexRequest = new CreateIndexRequest("indexname");
        IndicesAdminClient indices = es.getNode().client().admin().indices();
        indices.create(createIndexRequest).actionGet();

I get this:

11:27:32.397 [main] INFO  org.elasticsearch.http.HttpServer - publish_address {127.0.0.1:9200}, bound_addresses {[fe80::1]:9200}, {[::1]:9200}, {127.0.0.1:9200}
11:27:32.397 [main] INFO  org.elasticsearch.node.Node - started
Exception in thread "elasticsearch[V3ONMVd][clusterService#updateTask][T#1]" java.lang.NoClassDefFoundError: org/apache/logging/log4j/core/config/Configurator
    at org.elasticsearch.common.logging.Loggers.setLevel(Loggers.java:149)
    at org.elasticsearch.common.logging.Loggers.setLevel(Loggers.java:144)
    at org.elasticsearch.index.SearchSlowLog.setLevel(SearchSlowLog.java:111)
    at org.elasticsearch.index.SearchSlowLog.<init>(SearchSlowLog.java:106)
    at org.elasticsearch.index.IndexModule.<init>(IndexModule.java:127)
    at org.elasticsearch.indices.IndicesService.createIndexService(IndicesService.java:421)
    at org.elasticsearch.indices.IndicesService.createIndex(IndicesService.java:394)
    at org.elasticsearch.cluster.metadata.MetaDataCreateIndexService$1.execute(MetaDataCreateIndexService.java:352)
    at org.elasticsearch.cluster.ClusterStateUpdateTask.execute(ClusterStateUpdateTask.java:45)
    at org.elasticsearch.cluster.service.ClusterService.runTasksForExecutor(ClusterService.java:581)
    at org.elasticsearch.cluster.service.ClusterService$UpdateTask.run(ClusterService.java:920)
    at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:458)
    at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.runAndClean(PrioritizedEsThreadPoolExecutor.java:238)
    at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.run(PrioritizedEsThreadPoolExecutor.java:201)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.core.config.Configurator
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

it seems we are doomed to switch to log4j just because we use elasticsearch embedded within our tests :(

mvmn commented 7 years ago

it seems we are doomed to switch to log4j just because we use elasticsearch embedded within our tests :(

Actually this is stated in the thread - you have to have Log4J in classpath if you use ElasticSearch (be it server or client - doesn't matter).

You can still use other logging system - but you must have Log4J stuff in your classpath (which might cause conflicts for some logging systems or classpath-detection using things like Spring Boot).

kjussakov commented 7 years ago

Anyone managed to run the 5.* version of the TransportClient in Spring Boot/Spring IO Platform application? If so, please share how you managed to resolve the dependency conflicts. For me, it is either ClassNotFoundException for org.apache.logging.log4j.core.config.Configurator when log4j-core is not added as a dependency or SLF4JLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext with added log4j-core dependency. I am using SLF4J with Logback:

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.1.8</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.1.8</version>
    </dependency>        
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>transport</artifactId>
        <version>5.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-to-slf4j</artifactId>
        <version>2.7</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.7</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.21</version>
    </dependency>

I am trying to avoid the dependency shading overkill which I saw proposed in some places.

jasontedor commented 7 years ago

@kjussakov Would you please open a topic on the forum and link to it from here? However, when you open that topic, please provide a stack trace, I can not help you without a stack trace. Before you do that though, would you please look at my example on #22671 and see if it helps you solve your problems? In particular, I think that you might be able to remove the log4j-api dependency.

mvmn commented 7 years ago

Try this in your pom.xml

    <properties>
        <elasticsearch.version>5.1.2</elasticsearch.version>
    </properties>
imod commented 7 years ago

@kjussakov can you please add a comment with the link to the new topic?

kjussakov commented 7 years ago

Hi all, Thanks for your prompt reply! I will start with making a minimal possible example which has the issue I described and then open a new topic in the forum. I already started with a simple maven project with the dependencies I mentioned above. This also follows the official 5.* doc

Without any Spring related dependencies it seems it works so will try now to add more until I broke it.

Will keep you posted.

Best regards, Rumen

kjussakov commented 7 years ago

And here is the link to the new topic

I describe the workaround which I found to resolve the log4j dependency when running our tests with embedded Elasticsearch node.

laxika commented 7 years ago

@kjussakov Add

compile group: 'org.apache.logging.log4j', name: 'log4j-to-slf4j', version: '2.7'

It works for me with Spring Boot 1.4.2.

pritamm commented 7 years ago

Hi, I am using below configuration with elasticsearch 5.2.1, still getting error java.lang.ClassNotFoundException: org.apache.logging.log4j.core.Filter.

Can someone please help me resolve this?

my confuguration: "org.slf4j:slf4j-api:1.7.21", "org.apache.logging.log4j:log4j-api:2.7", "org.apache.logging.log4j:log4j-to-slf4j:2.7",

Stacktrace: Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/logging/log4j/core/Filter at java.lang.Class.getDeclaredConstructors0(Native Method) at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671) at java.lang.Class.getConstructor0(Class.java:3075) at java.lang.Class.getConstructor(Class.java:1825) at org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:134) at org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:125) at org.springframework.boot.logging.LoggingApplicationListener.onApplicationStartedEvent(LoggingApplicationListener.java:189) at org.springframework.boot.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:173) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:119) at org.springframework.boot.context.event.EventPublishingRunListener.publishEvent(EventPublishingRunListener.java:111) at org.springframework.boot.context.event.EventPublishingRunListener.started(EventPublishingRunListener.java:60) at org.springframework.boot.SpringApplicationRunListeners.started(SpringApplicationRunListeners.java:48) at org.springframework.boot.SpringApplication.run(SpringApplication.java:293) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1112) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1101) at com.audiencescience.media.search.Application.main(Application.java:14) Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.core.Filter at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 18 more

dadoonet commented 7 years ago

The stacktrace is not related to elasticsearch as far as I can see.

jasontedor commented 7 years ago

@pritamm If your issue is related to Elasticsearch (it does not look like it), please ask questions on the forum.

thaDude commented 7 years ago

@nik9000

We'd have used it if we liked the API better but we don't.

Dude...

Hello, the fact that ES 5.x org.elasticsearch.client transport artifact explicitly expects log4j2 2.7 made things quite hard for us. I don't understand the exact reason it's not using the slf4j API. Using log4j-over-slf4j is not an option since there will very likely be log4j-slf4j-impl in the class path to process the logs of "standard" libraries that don't make an explicit choice about the logging framework.

Our particular - not so fancy - use case: We use the ES 5.x client in the code for a Storm topology. The Storm distribution packs log4j2 2.1 - which is on the class path of all Storm processes on the cluster. ES client is not content with that version due to some new log4j2 API changes I guess so what are the options:

... not knowing the exact log4j2-specific features you rely on (being able to log objects?) it seems just using slf4j would have been more user-friendly :/

ctron commented 7 years ago

As I just ran into the same issue, I would like to share my solution to this. I know this is rather crude, but may work at least for some people.

https://github.com/ctron/de.dentrassi.elasticsearch.log4j2-mock/

I wrote a small mock implementation of log4j2-core which has enough functionality to trick Elasticsearch into thinking it configured log4j2 properly. So if you are using this in combination with org.apache.logging.log4j:log4j-to-slf4j then you should have all your output over SLF4J and simply ignore the internal calls to log4j-core which ES does to manipulate the log4j configuration during runtime.

pedorro commented 7 years ago

@ctron

https://github.com/ctron/de.dentrassi.elasticsearch.log4j2-mock/

Nice :) A terrible solution to a asinine problem. I'm using it!

fjalvingh commented 7 years ago

@ctron Thanks a million, this works like a charm. Good to see that someone tries for solutions when the developers aim for trouble 8-(

jasontedor commented 7 years ago

We do not aim for troubles @fjalvingh. In fact, we strive to make the use of Elasticsearch to developers joyful. We take this accusation very seriously so now I ask you to elaborate what you think it is that we are doing to aim for troubles so that we can rectify the situation. Otherwise, do not throw such statements around so loosely.

davidbilge commented 7 years ago

@ctron Why exactly did you go through all the trouble? log4j-to-slf4j seems to do exactly what you describe. Am I missing something?

(see my previous answer)

mvmn commented 7 years ago

@jasontedor You state that separating shared classes into shared JAR is non-trivial, but you never explain how come. We both know there's nothing non-trivial in creation of shared JAR and moving some classes from one JAR to another. Why don't you elaborate on the actual problem you have, so we could perhaps come up with some solutions to help you fix it, instead of just telling us how bad we are for even asking for a fix.

jasontedor commented 7 years ago

@mvmn It has been explained previously, the client is completely intertwined with the server, there is a lot more to it than merely moving shared classes.

instead of just telling us how bad we are for even asking for a fix

This never happened. We feel your pain. As said already in this thread: no one likes the entanglement, we wish it was not a thing, but we can't snap our fingers and make it go away.

fjalvingh commented 7 years ago

Well, @jasontedor, my remark came from a bit of frustration. I spent more than a day in upgrading our application to ElasticSearch 5.5. It proved to be an awful lot of work to keep a local node running while this worked very easily before. And the way to get that server to run was decidedly non-obvious. The additional trouble caused by ES hard depending on a logging implementation caused yet more grief.

I was also put off by the way discussions went here. It appeared that form was more important than fact. Instead of helping with solutions there are discussions on how to say things proper.

The fact of having to delve deeply into a lot of things, having to circumvent a lot things done to the code that made it hard to do what was previously simple, caused my remark.

jasontedor commented 7 years ago

I'm sorry you experienced so much frustration here due to the logging infrastructure. I hate that it's causing users pain. Would you please elaborate on the technical details of what caused you pain so we can factor it into our thinking? I had hoped that making it clear that we are bound to the Log4j API but not the implementation for the client would help clarify the situation. Can you explain why this is not the case?

It appeared that form was more important than fact. Instead of helping with solutions there are discussions on how to say things proper.

Form is important. We have a community here, we have standards, we will maintain them, and we will not tolerate being treated as adversaries.

Also, I disagree we have not been helping in this thread. We've provided example implementations, clarified the dependencies, listened to feedback, etc.

fjalvingh commented 7 years ago

The pain was caused by more than just the logging infrastructure ;) My main challenge was to get an embedded server node running as that was the solution chosen a few years ago. This proved to be hard. First because NodeBuilder was removed and even though the notes said that similar functionality could be had by using the Node constructor with Settings this proved to be hard to do (I needed a plugin to get HTTP functionality and for that you need to override a class). After that the logging issue appeared. The core issue here is that ES depends on a logging implementation (log4j2-core) because it apparently tries to change the logging configuration at runtime.

Using a bridge jar works fine for switching the loggers themselves to send their output to another logger implementation. But the bridge does not contain the parts that ES uses to change the configuration (as they are implementation dependent). Hence the error, hence the frustration, and hence the happiness with @ctron's great contribution. Switching logging implementations is not a small issue for us. I think ES is a great product, don't get me wrong. But with great power comes great responsibility ;) So making changes like these can hurt.

As far as helping is concerned I was less than happy, and that showed.

I fully understand you want to have normal standards in communication. I do not think I crossed any line here.

thaDude commented 7 years ago

I am wondering if the sort-of accepted solution to the issue: using the log4j-to-slf4j bridge does not bear some risks. Quoting from the log4j2 documentation:

Use of the Log4j 2 SLF4J Binding (log4j-slf4j-impl-2.0.jar) together with the SLF4J adapter (log4j-to-slf4j-2.0.jar) should never be attempted, as it will cause events to endlessly be routed between SLF4J and Log4j 2.

I think that using log4j-slf4j-impl is very common in cases where applications follow the "standard" approach of using the slf4j API and binding the implementation later on.

Perhaps people were wondering why Elasticsearch doesn't do the same way. A comment further up mentioned that you don't like the slf4j API.

jasontedor commented 7 years ago

My main challenge was to get an embedded server node running as that was the solution chosen a few years ago.

@fjalvingh I'm sorry to hear about the troubles that you're having with embedding the server. Unfortunately, we do not support this use case anymore. I would encourage you to migrate to standing up a real server instance (I'm assuming this is for testing, this is what we encourage users to do now).

The core issue here is that ES depends on a logging implementation (log4j2-core) because it apparently tries to change the logging configuration at runtime.

This is correct, the server binds the configuration during startup and that requires core. This is not the case for the transport client which is why we can get away with depending on the API but not the implementation.

I fully understand you want to have normal standards in communication. I do not think I crossed any line here.

I agree, you did not cross any line. However, since you asserted that the developers aim for troubles, and then later that we were focusing on form over fact instead of helping users, I must explain why we focus on form when we see non-collaborative behavior that we will not tolerate, and disagree with your assertions that we are aiming for troubles and not trying to help.

jasontedor commented 7 years ago

Perhaps people were wondering why Elasticsearch doesn't do the same way. A comment further up mentioned that you don't like the slf4j API.

I can explain this. We chose Log4j as our logging backend. We chose this for specific reasons:

When an abstraction/facade like SLF4J is used:

ctron commented 7 years ago

All in all it simply looks to me as if like ES has different priorities than some of its users. And those priorities have changed over time. And in general that is fine.

But that also causes troubles for users which depend on those features. So those people will look for alternatives and may ask themselves why those changes were made.

As ES is an open source project, tinkering around with it is a valid approach. Now the people behind ES can approach this on two ways. Take those people seriously and try to embrace those workarounds, making their life simpler while maintaining their own priorities. Or stick to their position and don't care, making it more complicated for others in the future.

I don't think I need to tell anyone which the road to success is.

jstultz commented 7 years ago

The issue I see here is that a decision was made that an abstraction layer like slf4j was not needed based on a false premise: that the code using it was only used as a server, not as a library, when that is not actually true. I understand that the dev team would like it not to be true at some point in the future, but the fact remains that it is used as a library, and that perhaps the most friendly thing to do for developers on the JVM who don't (by your own admission) have any great client alternatives except for the one that has a hard dependency on log4j2, might have been to use slf4j even if you didn't like the API better than log4j2.

As for some of the specific reasons listed above for using log4j directly:

the flexibility that it provides our end users to configure logging (e.g., rolling logs, compressing logs, various appenders, features that our users were asking for, etc.)

As far as I know, using SLF4J backed by log4j does not prevent or eliminate this flexibility.

we only want to support one logging backend, maintaining one is already hard enough

So write your code to support SLF4J, and your configuration and maintenance tools to support a log4j backing, and make it clear that using other backends in ES servers is unsupported.

I understand that there are, as always, tradeoffs involved, but the discussion thus far doesn't really fully cover the tradeoffs involved in the decision that was actually made (i.e. should an abstraction layer be used in code that is distributed as a library)

jasontedor commented 7 years ago

The issue I see here is that a decision was made that an abstraction layer like slf4j was not needed based on a false premise: that the code using it was only used as a server, not as a library, when that is not actually true.

I'm sorry, but this is simply false. We did consider the impact that using Log4j directly would have on users of the transport client. We clearly did not foresee all the problems this might cause, but we absolutely did deliberate it and truly considered the impact it would have on our users before going down this path.

As for some of the specific reasons listed above for using log4j directly:

the flexibility that it provides our end users to configure logging (e.g., rolling logs, compressing logs, various appenders, features that our users were asking for, etc.)

As far as I know, using SLF4J backed by log4j does not prevent or eliminate this flexibility.

I think there is a miscommunication here. I did not claim nor intend to imply that using SLF4J would prevent this. I was merely enumerating reasons why we chose Log4j and why we chose to not use the SLF4J facade, it is not necessarily the case that all reasons provided cover both aspects of our decision making here. I'm sorry for the confusion.

jstultz commented 7 years ago

I'm sorry, but this is simply false. We did consider the impact that using Log4j directly would have on users of the transport client. We clearly did not foresee all the problems this might cause, but we absolutely did deliberate it and truly considered the impact it would have on our users before going down this path.

Well, perhaps you'll forgive me for making an assumption based on what I've read in this conversation thus far. The statement made very early on in this conversation:

Because Elasticsearch is a server we don't feel the need to talk to a logging abstraction layer. We'd have used it if we liked the API better but we don't.

gave no indication that consideration was given to Java clients at the time, and was even in the present tense, implying that the need for an abstraction layer was still not felt. That said, I trust you that it was, but the impression I have from reading this conversation was that the transport client was an afterthought, so I guess there was a miscommunication issue there.

jasontedor commented 7 years ago

I would really like to solve the technical problems that users are having here. I think that the actual problems are getting lost in the discussion (this is not to say that we should stop the discussion, we should not stop as we truly welcome feedback from the community here).

I would like to ask this: if you're having a technical problem with a supported configuration (i.e., not embedded which was raised as a problem here a few times yet we do not support it) please open a new issue, ping me on the issue, and link to it from here. If you're having a technical problem covered by a newly opened issue, please comment or 👍 the issue.

jasontedor commented 7 years ago

Well, perhaps you'll forgive me for making an assumption based on what I've read in this conversation thus far.

Yes, of course!

The statement made very early on in this conversation:

Because Elasticsearch is a server we don't feel the need to talk to a logging abstraction layer. We'd have used it if we liked the API better but we don't.

That statement is unfortunate as it does not fully reflect the reality of internal conversations and decisions correctly (I'm sorry @nik9000); given that statement I can see why you reached the conclusion that you did. For the record:

Obviously the real world is messier than the samples that I experimented with so it appears there are unforeseen problems that we have to solve. Let's clearly enumerate those problems and see what we can do.

jasontedor commented 7 years ago

Take those people seriously and try to embrace those workarounds, making their life simpler while maintaining their own priorities. Or stick to their position and don't care, making it more complicated for others in the future.

Sorry, this is a false dichotomy.