Skip to content
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

io.smallrye.graphql.entry.http.GraphQLServerWebSocket java.lang.NoClassDefFoundError: org.jboss.logging.Logger #2018

Open
urbandroid opened this issue Jan 28, 2024 · 15 comments

Comments

@urbandroid
Copy link

I'm trying to GraphQL server to run on OpenLiberty and it complains at start that :

`[WARNING ] CWNEN0047W: Resource annotations on the fields of the io.smallrye.graphql.entry.http.GraphQLServerWebSocket class will be ignored. The annotations could not be obtained because of the exception : java.lang.NoClassDefFoundError: org.jboss.logging.Logger
[AUDIT ] CWWKT0016I: Web application available (default_host): http://ac6a5b861e67:9080/deneme2-web/
[ERROR ] SRVE0283E: Exception caught while initializing context: java.lang.NoClassDefFoundError: org.jboss.logging.Logger
at io.smallrye.graphql.entry.http.SmallRyeGraphQLServletLogging.(SmallRyeGraphQLServletLogging.java:17)
at io.smallrye.graphql.entry.http.IndexInitializer.createIndex(IndexInitializer.java:55)
at io.smallrye.graphql.entry.http.StartupListener.contextInitialized(StartupListener.java:55)
at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextCreated(WebApp.java:2465)
at [internal classes]

[ERROR ] SRVE0265E: Error occured while notifying listeners of web application start: java.lang.NoClassDefFoundError: org.jboss.logging.Logger
at io.smallrye.graphql.entry.http.SmallRyeGraphQLServletLogging.(SmallRyeGraphQLServletLogging.java:17)
at io.smallrye.graphql.entry.http.IndexInitializer.createIndex(IndexInitializer.java:55)
at io.smallrye.graphql.entry.http.StartupListener.contextInitialized(StartupListener.java:55)
at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextCreated(WebApp.java:2465)
at [internal classes]

[AUDIT ] CWWKZ0012I: The application deneme2-ear was not started.
[AUDIT ] CWWKT0017I: Web application removed (default_host): http://ac6a5b861e67:9080/deneme2-web/
[ERROR ] SRVE0285E: Exception caught while destroying context: java.lang.NoClassDefFoundError: io.smallrye.graphql.entry.http.SmallRyeGraphQLServletLogging (initialization failure)
at java.base/java.lang.J9VMInternals.initializationAlreadyFailed(J9VMInternals.java:156)
at io.smallrye.graphql.entry.http.StartupListener.contextDestroyed(StartupListener.java:69)
at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextDestroyed(WebApp.java:2697)
at [internal classes]
`

Server shouldn't depend on Application server specific dependencies so that any Jakarta EE server can run it.

@jmartisk
Copy link
Member

That's not an application-server-specific dependency, it's just the logging facade that SmallRye uses. I haven't tried running on OpenLiberty, but generally the appserver should make sure that applications receive all the required dependencies. I know there have been users successfully using SmallRye GraphQL with OpenLiberty, so maybe try asking about it in the OpenLiberty repo?

@urbandroid
Copy link
Author

urbandroid commented Jan 29, 2024

@jmartisk is these two dependencies should be enough to run?

	<dependency>
		<groupId>org.eclipse.microprofile.graphql</groupId>
		<artifactId>microprofile-graphql-api</artifactId>
		<version>2.0</version>
	</dependency>
	
	<!-- https://mvnrepository.com/artifact/io.smallrye/smallrye-graphql -->
	<dependency>
		<groupId>io.smallrye</groupId>
		<artifactId>smallrye-graphql</artifactId>
		<version>2.7.1</version>
	</dependency>

I want code first approach so configurations from server side is not acceptable openliberty and wildflys suggested method requires server side configuration.
here is my simple test class:

import jakarta.ws.rs.ApplicationPath;
import org.eclipse.microprofile.graphql.GraphQLApi;
import org.eclipse.microprofile.graphql.Query;

@ApplicationPath("/test")
@GraphQLApi
public class MyGraphQLResource {

   @Query
   public String hello() {
        return "Hello, GraphQL!";
    }

@jmartisk
Copy link
Member

Sorry, I really don't know much of anything about OpenLiberty. I can just point you to their guide and quickstart at https://github.com/openliberty/guide-microprofile-graphql or suggest to try filing an issue in their repo. Here we only develop the smallrye-graphql project itself, then how the OpenLiberty team integrates this project, that's their separate thing. Or I can suggest to use Quarkus instead if you can (https://github.com/quarkusio/quarkus-quickstarts/tree/main/microprofile-graphql-quickstart), in this case I would be able to help more, because I also maintain the Quarkus integration of smallrye-graphql.

I want code first approach so configurations from server side is not acceptable openliberty and wildflys suggested method requires server side configuration.

Not sure I understand you here. With MicroProfile GraphQL, there's only the code-first approach, there's no support for contract-first approach (which would mean having your API class generated from a supplied GraphQL schema). I don't see what that has to do with server-side configuration.

@urbandroid
Copy link
Author

Wildfly and Openliberty suggest configuring server to use GraphQL https://www.wildfly.org/news/2020/08/13/Introducing-the-WildFly-GraphQL-feature-pack/

https://openliberty.io/docs/latest/microprofile-graphql.html

<feature>mpGraphQL-2.0</feature>

I don't want to configure server side so that no matter the server (wildfly, openliberty, payara, tomcat ...) it will work. App server agnostic. The way to do it is adding to project dependencies. I have managed to
make it work with payara, wildfly and openliberty but open liberty fails if


		<!-- https://mvnrepository.com/artifact/org.jboss.logging/jboss-logging -->
		<dependency>
			<groupId>org.jboss.logging</groupId>
			<artifactId>jboss-logging</artifactId>
			<version>3.5.3.Final</version>
		</dependency>

not added.

Here is the current branch https://github.com/urbandroid/graphql-jakarta/tree/debug

@jmartisk
Copy link
Member

So you want just one Maven project that produces an archive that you can use, without changes, with Payara, WildFly, Tomcat and OpenLiberty, and it should deploy on all of them with the vanilla configuration (out-of-the-box)? I think that may be too much of an expectation and probably impossible. Jakarta EE servers try to be interoperable, but not to such an extent. Also, GraphQL is not a built-in functionality of them, you have to add it extra (with WildFly, the feature pack should do most of the work for you, but I'm not sure about others, you will probably have to register some servlets manually etc.)

@t1
Copy link
Collaborator

t1 commented Jan 31, 2024

All JEE application servers should be able to run the same application archive (as an ear, or nowadays more often war). Only is some cases, the servers may need some special configuration; and they do when it comes to MP GraphQL, as it's not (yet) part of the officially supported standards. OpenLiberty needs more configuration that WildFly, if I remember correctly my sparse experiments mit OpenLiberty. But it's only a feature to be enabled, while on WildFly you need to install a full feature pack.

In order to make it run at all, @urbandroid has added a dependency to jboss-logging to the application, but that's not the proper way, as the application should contain (ideally) no libraries at all, and only use provided dependencies to the standards (MP GraphQL in this case). jboss-loggin is a provided dependency in smallrye-graphql-servlet, because we decided to use that for logging. But it has been like that for a long time, so I assume that there must be a way to make it work properly also on OpenLiberty, I just don't know, as I mainly use WildFly. I assume there has to be some feature containing jboss-logging, and I think it should be activated by the mpGraphql feature automatically.

As @jmartisk already wrote: If it doesn't work like in the guide (https://openliberty.io/guides/microprofile-graphql.html), you should probably open an issue at OpenLiberty.

@urbandroid
Copy link
Author

I have opened a issue at open liberty repo OpenLiberty/open-liberty#27534

@NottyCode
Copy link

@t1 based on the bug report to open liberty the guide has not been followed and they are trying to package smallrye graphql in their application. If that is their intent and desire they can do so, but they would be required to package the dependencies of smallrye graphql in their applications. There is no requirement that a Jakarta EE runtime provide jboss logging.

I would imagine a similar issue would occur when trying to package smallrye graphql in a web app deployed to Tomcat or Jetty since I don't think either of those provide jboss logging either. It seems to me that the jboss logging dependency should be compile rather than provided since it isn't provided in all Jakarta EE runtimes.

If they were following the guide you pointed them at then you would be correct that they would not see this ClassDefNotFoundError

@t1
Copy link
Collaborator

t1 commented Feb 1, 2024

Okay, I didn't catch that. On some containers, it may be necessary to packaging a GraphQL implementation into the application (including jboss-logging). But when deploying to OpenLiberty or WildFly, this only makes sense, when you need full control over the exact version used. Otherwise I'd strongly recommend to build thin-wars and let the container control the dependencies... that has just way too strong benefits.

I assume that changing the dependency from provided to compile would then make it necessary to exclude the dependency in Quarkus and WildFly; maybe it would also required a change to the OpenLiberty GraphQL feature. But I'm not 100% sure.

@NottyCode
Copy link

I agree that I would recommend using the Liberty or WildFly packaging.

In terms of provided vs compile I don't think it would be necessary to exclude the dependency in Quarkus, WildFly or OpenLiberty because it is optional in all those cases. I think there are three scenarios:

  1. Runtime isn't configured with smallrye graphql support. This is obvious, the war needs to package jboss logging and this would fix that.
  2. Runtime is configured with smallrye graphql support. In this case the worst case scenario would be that the war contains jboss logging, but it'll be ignored for the copy packaged in the underlying runtime.
  3. Runtime is defined based on maven dependencies (I call this out because I think Quarkus is like this). In this case I would expect maven would combine the dependencies of smallrye graphql and quarks to come up with a single version of jboss logging to run for the application.

So essentially I think this change will enable a bunch of scenarios people expect to work and I think the worst case scenario is it would add bloat to the war file, but I don't think anything would break.

@t1
Copy link
Collaborator

t1 commented Feb 2, 2024

but it'll be ignored for the copy packaged in the underlying runtime

IIUC, it's the other way around. Even worse: it might be picked for some calls but not for all.

@phillip-kruger
Copy link
Member

@jmartisk why are we using JBoss logging ? As far as I remembered we only use JUL ?

@jmartisk
Copy link
Member

jmartisk commented Feb 5, 2024

No we have JBoss Logging, like most other SmallRye projects (looking at their code, perhaps except Mutiny)

@phillip-kruger
Copy link
Member

O yes you are right. We have the i18n stuff ... I remember now.

@NottyCode
Copy link

@t1 class loading uses the parent class loader first, so assuming the app server provided classes are on the parent class loader (which would be the case in Liberty if we shipped this code) then the Liberty version would be used ahead of the application one.

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

No branches or pull requests

5 participants