smallrye-graphql
smallrye-graphql copied to clipboard
io.smallrye.graphql.entry.http.GraphQLServerWebSocket java.lang.NoClassDefFoundError: org.jboss.logging.Logger
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.
[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.
[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.
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?
@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!";
}
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.
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
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.)
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.
I have opened a issue at open liberty repo https://github.com/OpenLiberty/open-liberty/issues/27534
@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
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.
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:
- Runtime isn't configured with smallrye graphql support. This is obvious, the war needs to package jboss logging and this would fix that.
- 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.
- 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.
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.
@jmartisk why are we using JBoss logging ? As far as I remembered we only use JUL ?
No we have JBoss Logging, like most other SmallRye projects (looking at their code, perhaps except Mutiny)
O yes you are right. We have the i18n stuff ... I remember now.
@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.