Disable introspection query in graphql java tools spring boot - java

I am facing issues while disabling the introspection query in a spring boot graphql project on a get endpoint query parameter.
I was replicating this by using one of the GET endpoint and using the below parameter
baseurl/servicename/insight_graph?query=fragment+FullType+on+__Type+{++kind++name++description++fields(includeDeprecated%3a+true)+{++++name++++description++++args+{++++++...InputValue++++}++++type+{++++++...TypeRef++++}++++isDeprecated++++deprecationReason++}++inputFields+{++++...InputValue++}++interfaces+{++++...TypeRef++}++enumValues(includeDeprecated%3a+true)+{++++name++++description++++isDeprecated++++deprecationReason++}++possibleTypes+{++++...TypeRef++}}fragment+InputValue+on+__InputValue+{++name++description++type+{++++...TypeRef++}++defaultValue}fragment+TypeRef+on+__Type+{++kind++name++ofType+{++++kind++++name++++ofType+{++++++kind++++++name++++++ofType+{++++++++kind++++++++name++++++++ofType+{++++++++++kind++++++++++name++++++++++ofType+{++++++++++++kind++++++++++++name++++++++++++ofType+{++++++++++++++kind++++++++++++++name++++++++++++++ofType+{++++++++++++++++kind++++++++++++++++name++++++++++++++}++++++++++++}++++++++++}++++++++}++++++}++++}++}}query+IntrospectionQuery+{++__schema+{++++queryType+{++++++name++++}++++mutationType+{++++++name++++}++++types+{++++++...FullType++++}++++directives+{++++++name++++++description++++++locations++++++args+{++++++++...InputValue++++++}++++}++}}
and with the below dependencies
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.4.1</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.4.1</version>
<exclusions>
<exclusion>
<artifactId>jackson-module-kotlin</artifactId>
<groupId>com.fasterxml.jackson.module</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>5.4.1</version>
</dependency>
This works pretty well when we request the same using post and with the below request body and using graphql.tools.introspection-enabled=false and
POST baseurl/servicename/insight_graph
[
{
"operationName": "IntrospectionQuery",
"variables": {},
"query": "query IntrospectionQuery {__schema {queryType { name },mutationType { name },subscriptionType { name },types {...FullType},directives {name,description,args {...InputValue},onOperation,onFragment,onField}}}\nfragment FullType on __Type {kind,name,description,fields(includeDeprecated: true) {name,description,args {...InputValue},type {...TypeRef},isDeprecated,deprecationReason},inputFields {...InputValue},interfaces {...TypeRef},enumValues(includeDeprecated: true) {name,description,isDeprecated,deprecationReason},possibleTypes {...TypeRef}}\nfragment InputValue on __InputValue {name,description,type { ...TypeRef },defaultValue}\nfragment TypeRef on __Type {kind,name,ofType {kind,name,ofType {kind,name,ofType {kind,name}}}}"
}
]
I also tried this via spring filters and it works fine
Is there any way to disable introspection via spring boot property for this?

Related

I got this message: Cannot construct instance of `reactor.core.publisher.Mono`

I used Jersey and Webflux with R2DBC. after send the POST via the postman I got this message " Cannot construct instance of reactor.core.publisher.Mono "
This is my JerseyConfiguration:
#Component
public class JerseyConfiguration
extends ResourceConfig {
public JerseyConfiguration() {
register(ProductController.class, 1);
}
}
and this is my Controller:
#Path("/v1")
#Controller
public class ProductController {
#Autowired
private ProductService productService;
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("/product")
public Mono<Product> createProduct(#RequestBody Mono<Product> productMono){
return productMono.flatMap(this.productService::createProduct);
}
}
and this sis my service:
#Service
public class ProductService {
#Autowired
private ProductRepository repository;
public Mono<Product> createProduct(final Product product){
return this.repository.save(product);
}
}
and also this my pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Now, this is my problem; I got this message from the postman:
Cannot construct instance of `reactor.core.publisher.Mono` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream); line: 1, column: 1]
Please let me know how to solve that problem.
Thank you
You cannot mix WebFlux and Jersey. You should choose one or the other, not both. They both provide an HTTP server engine, but:
Jersey is a Servlet JAX-RS implementation, it does not know anything about reactive streams, Mono, Flux, etc.
Webflux is the Spring HTTP server engine based on reactive streams and async Netty HTTP server.
If you look at Spring Boot reference documentation, section 3.5: Web, you will see that Jersey is one of the available engines, competing with other possible engines, i.e Web MVC and web reactive (webflux).
So, the answer is : Jersey is incompatible with Webflux, and you must choose between Webflux reactive Web and Spring rest annotation, or Jersey and Jax_RS without using Mono/Flux as return-type.
Note 1 : You should annotate your class with #RestController whe using webflux, so it understand that method return is the HTTP response body (see the last paragraph of reference documentation section 1.4.1: #Controller for details.
Note 2 : If you really want to use jersey, but you still require to consume Mono objects from other parts of your system, you might use one of the conversion functions provided by Reactor to return an object that jersey can work with. For example, on Mono object, you will find a toFuture() method. You could also block(), but it could be dangerous.

Camel with servlet not starting in quarkus

I am trying to start my application with Apache camel and Quarkus but it giving me below error:
At least one bean matched the required type and qualifiers but was marked as unused and removed during build
Removed beans:
- CLASS bean org.apache.camel.component.servlet.CamelHttpTransportServlet [types=[class javax.servlet.http.HttpServlet, interface java.io.Serializable, class org.apache.camel.http.common.CamelServlet, interface javax.servlet.ServletConfig, interface org.apache.camel.http.common.HttpRegistryProvider, class org.apache.camel.component.servlet.CamelHttpTransportServlet, class javax.servlet.GenericServlet, interface javax.servlet.Servlet], qualifiers=[#javax.enterprise.inject.Default(),
#javax.enterprise.inject.Any()]]
Required type: class org.apache.camel.component.servlet.CamelHttpTransportServlet
Required qualifiers: [#javax.enterprise.inject.Default()]
Solutions:
- Application developers can eliminate false positives via the #Unremovable annotation
- Extensions can eliminate false positives via build items, e.g. using the UnremovableBeanBuildItem
I am not sure what am I missing:
application.properties
camel.context.name=aiv
quarkus.camel.servlet.url-patterns = /rest/*
pom.xml
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-main</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-platform-http</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-log</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-timer</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-servlet</artifactId>
</dependency>
public class CamelRoute extends RouteBuilder {
#Override
public void configure() {
restConfiguration()
.component("servlet");
...
}
}
Please let me know what wrong am I doing?
Unless you genuinely need Servlet support for some reason, then you can rely on camel-quarkus-platform-http to handle the HTTP transport for the Camel REST DSL.
You're dependencies can be simplified to:
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-main</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-log</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-timer</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-rest</artifactId>
</dependency>
There's more information in the Camel Quarkus documentation:
https://camel.apache.org/camel-quarkus/latest/reference/extensions/platform-http.html

How to override DataFetcherExceptionHandler in GraphQL Java?

I am using the following starter for Graphql integration
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>6.0.1</version>
</dependency>
I am not sure how to override the SimpleDataFetcherExceptionHandler with my own CustomExceptionHandler. The library already autowires a lot of stuff. Do I need to create a separate configuration for graphQl object? The documentation is not much helpful.
I also tried to integrate #ControllerAdvice to my Graphql java spring boot application but the errors are not matched by the exception handlers inside it. They are handled by GraphQl error handler. How does error propagates inside Graphql?
How can I change this behaviour?
I have this and it's working for me. Pretty much regular spring stuff for exception handling, but there is no #ControllerAdvice (it's kotlin btw, if you can't understand - let me know, but I think it's pretty clear even without kotlin knowledge).
import org.springframework.web.bind.annotation.ExceptionHandler
import com.oembedler.moon.graphql.boot.error.ThrowableGraphQLError
internal class GraphQLExceptionHandler {
#ExceptionHandler(AppException::class)
fun handleGenericException(ex: AppException): ThrowableGraphQLError {
return ThrowableGraphQLError(ex)
}
#ExceptionHandler(Exception::class)
fun handleGenericException(ex: Exception): ThrowableGraphQLError {
return ThrowableGraphQLError(TechnicalException())
}
}
#Configuration
internal open class GraphQLConfiguration {
#Bean
open fun graphQLExceptionHandler(): GraphQLExceptionHandler {
return GraphQLExceptionHandler()
}
}
I have quite a few dependencies tho, in case they matter here:
<graphql.version>5.4.1</graphql.version>
<graphql-datetime-spring-boot-starter.version>1.4.0</graphql-datetime-spring-boot-starter.version>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>${graphql.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>${graphql.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>voyager-spring-boot-starter</artifactId>
<version>${graphql.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>${graphql.version}</version>
</dependency>
<dependency>
<groupId>com.zhokhov.graphql</groupId>
<artifactId>graphql-datetime-spring-boot-starter</artifactId>
<version>${graphql-datetime-spring-boot-starter.version}</version>
</dependency>

Helidon MP OpenAPI aren't generating a updated openapi endpoint response

I'm currently building a microservice-based on Helidon Microprofile following guides and tutorials from Oracle themselves, but I've run into a problem related to the 'Automatic OpenAPI specification generator' when using Annotations.
My POM consists of an MP bundle and integrations to make it work with Hibernate-provided JPA.
Even after setting up all the annotations on my Resource, it doesn't generate an updated specification.
POM
<dependencies>
<dependency>
<groupId>io.helidon.microprofile.bundles</groupId>
<artifactId>helidon-microprofile</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jandex</artifactId>
<version>2.1.1.Final</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.helidon.integrations.cdi</groupId>
<artifactId>helidon-integrations-cdi-datasource-hikaricp</artifactId>
<version>1.4.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.helidon.integrations.cdi</groupId>
<artifactId>helidon-integrations-cdi-jta-weld</artifactId>
<version>1.4.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.helidon.integrations.cdi</groupId>
<artifactId>helidon-integrations-cdi-hibernate</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>2.2.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.29.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.3</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>jwks-rsa</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
</dependencies>
I'm only using Annotations specified in the guides and #OpenAPIDefinition for defining things like Title and Licence.
RESOURCE
#OpenAPIDefinition(
info = #Info(
title = "Newsletter Microservice",
version = "1.0", description = "Microservice in charge of handling newsletter",
license = #License(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0"),
contact = #Contact(name = "Email", url = "mailto:email")
),
tags = {
#Tag(name = "public"), #Tag(name = "private")
}
)
#Path("/newsletter")
#RequestScoped
public class NewsletterClientResource {
LOG
Connected to the target VM, address: '127.0.0.1:0', transport: 'socket'
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2019.12.02 20:01:19 INFO org.jboss.weld.Version Thread[main,5,main]: WELD-000900: 3.1.1 (Final)
2019.12.02 20:01:20 INFO org.jboss.weld.Bootstrap Thread[main,5,main]: WELD-ENV-000020: Using jandex for bean discovery
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.jboss.weld.util.bytecode.ClassFileUtils$1 (file:/C:/Users/Brenno%20Fagundes/.m2/repository/org/jboss/weld/weld-core-impl/3.1.1.Final/weld-core-impl-3.1.1.Final.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int)
WARNING: Please consider reporting this to the maintainers of org.jboss.weld.util.bytecode.ClassFileUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2019.12.02 20:01:21 INFO org.jboss.weld.Event Thread[main,5,main]: WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jersey.ext.cdi1x.internal.ProcessAllAnnotatedTypes.processAnnotatedType(#Observes ProcessAnnotatedType<?>, BeanManager) receives events for all annotated types. Consider restricting events using #WithAnnotations or a generic type with bounds.
2019.12.02 20:01:21 INFO org.jboss.weld.Event Thread[main,5,main]: WELD-000411: Observer method [BackedAnnotatedMethod] private io.helidon.microprofile.openapi.IndexBuilder.processAnnotatedType(#Observes ProcessAnnotatedType<X>) receives events for all annotated types. Consider restricting events using #WithAnnotations or a generic type with bounds.
2019.12.02 20:01:22 INFO org.jboss.weld.Bootstrap Thread[main,5,main]: WELD-ENV-002003: Weld SE container 404f642b-892f-4676-960e-8df848aee3a3 initialized
2019.12.02 20:01:22 INFO io.helidon.microprofile.security.SecurityMpService Thread[main,5,main]: Security extension for microprofile is enabled, yet security configuration is missing from config (requires providers configuration at key security.providers). Security will not have any valid provider.
2019.12.02 20:01:22 INFO io.smallrye.openapi.api.OpenApiDocument Thread[main,5,main]: OpenAPI document initialized: io.smallrye.openapi.api.models.OpenAPIImpl#7793ad58
2019.12.02 20:01:23 INFO io.helidon.webserver.NettyWebServer Thread[main,5,main]: Version: 1.4.0
2019.12.02 20:01:24 INFO io.helidon.webserver.NettyWebServer Thread[nioEventLoopGroup-2-1,10,main]: Channel '#default' started: [id: 0x4e1f119b, L:/0:0:0:0:0:0:0:0:7200]
2019.12.02 20:01:24 INFO io.helidon.microprofile.server.ServerImpl Thread[nioEventLoopGroup-2-1,10,main]: Server initialized on http://localhost:7200 (and all other host addresses) in 5254 milliseconds.
BUMP, also, the generation works using custom filters and models, a static definition in META-INF also works. Currently using JDK 13.
EDIT: this is my Application class after Tim Quinn's suggested modifications.
APPLICATION CLASS
#ApplicationScoped
#ApplicationPath("/")
#OpenAPIDefinition(
info = #Info(
title = "Newsletter Microservice",
version = "1.0", description = "Microservice in charge of handling newsletter",
license = #License(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0"),
contact = #Contact(name = "Email", url = "mailto:john.doe#gmail.com")
),
tags = {
#Tag(name = "public"), #Tag(name = "private")
}
)
public class NewsletterApplication extends Application {
#Override
public Set<Class<?>> getClasses(){
HashSet<Class<?>> classes = new HashSet<Class<?>>();
classes.add(NewsletterClientResource.class);
return classes;
}
}
GENERATED FILE
---
openapi: 3.0.1
info:
title: Generated API
version: "1.0"
paths: {}
Brenno,
You didn't show your updated source code, but I'm assuming you added the #OpenAPIDefinition annotation to the quickstart GreetResource class, is that right?
That annotation's attributes describe the whole application, not a subset of its resources, so try moving the annotation to the GreetApplication class instead:
#ApplicationScoped
#ApplicationPath("/")
#OpenAPIDefinition(info = #Info(title = "QuickStart API", version = "1.1"))
public class GreetApplication extends Application {...}
That should work. I just tried this on the generated Helidon MP quickstart example source, rebuilt, and the server returned the expected results.
Here is the diff for the change I made:
diff --git a/examples/quickstarts/helidon-quickstart-mp/src/main/java/io/helidon/examples/quickstart/mp/GreetApplication.java b/examples/quickstarts/helidon-quickstart-mp/src/main/java/io/helidon/examples/quickstart/mp/GreetApplication.java
index fd140738..cca60da2 100644
--- a/examples/quickstarts/helidon-quickstart-mp/src/main/java/io/helidon/examples/quickstart/mp/GreetApplication.java
+++ b/examples/quickstarts/helidon-quickstart-mp/src/main/java/io/helidon/examples/quickstart/mp/GreetApplication.java
## -23,12 +23,15 ## import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import io.helidon.common.CollectionsHelper;
+import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition;
+import org.eclipse.microprofile.openapi.annotations.info.Info;
/**
* Simple Application that produces a greeting message.
*/
#ApplicationScoped
#ApplicationPath("/")
+#OpenAPIDefinition(info = #Info(title = "QuickStart API", version = "1.1"))
public class GreetApplication extends Application {
#Override
And here is the beginning of the updated OpenAPI document returned from the server:
---
openapi: 3.0.1
info:
title: QuickStart API
version: "1.1"
paths:
The title and version have changed, as expected.
Case 1 : You are using jandex and your /openapi is not getting updated.
If you are using jandex, there is a high chance that your jandex.idx is not getting updated. You can do this by running mvn process-classes
Case 2 : You are not using jandex and when you hit /openapi you get somewhat blank response.
This seems to be an issue with Helidon. The dependencies helidon-integrations-cdi-jpa, helidon-integrations-cdi-jta, helidon-integrations-cdi-eclipselink etc... contains jandex.idx and Helidon now thinks that jandex is enabled and it
will read only from those jandex files, skipping your resources. So for the time-being, you can include jandex plugin to solve the issue.

SOAP over Websocket with Appache CXF and Embedded Jetty

I have been trying to set a a SOAP endpoint with Websocket as transport protocol via CXF and implement invoke it via CXF. With Embeded jetty. I have tried a couple of approaches non of the aproaches worked unfortunatly. Here is what I did:
Aproach 1. According to CXF documentation websocket is supported as transport protocol and its support is given via
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-websocket</artifactId>
<version>3.3.2</version>
</dependency>
I have setup the following dependencies:
<dependency>
<groupId>org.asynchttpclient</groupId>
<artifactId>async-http-client</artifactId>
<version>2.0.39</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.3.2</version>
</dependency>
The code I executo is the following:
Endpoint endpoint = Endpoint.create(new MyHelloWorldServicePortType() {
#Override
public String sayHello(HelloMessage message) throws FaultMessage {
return message.sayHello();
}
};
((org.apache.cxf.jaxws.EndpointImpl)endpoint).getFeatures().add(new
WSAddressingFeature());
endpoint.publish("ws://localhost:8088/MyHelloWorldService" );
URL wsdlDocumentLocation = new URL("file:/path to wsdl file");
String servicePart = "MyHelloWorldService";
String namespaceURI = "mynamespaceuri";
QName serviceQN = new QName(namespaceURI, servicePart);
Service service = Service.create(wsdlDocumentLocation, serviceQN);
MyHelloWorldServicePortType port = service.getPort( MyHelloWorldServicePortType.class);
portType.sayHello(new HelloMessage("Say Hello"));
The result of this code is:
SEVERE: [ws] onError java.util.concurrent.TimeoutException: Request
timeout to not-connected after 60000 ms at
org.asynchttpclient.netty.timeout.TimeoutTimerTask.expire(TimeoutTimerTask.java:43)
at
org.asynchttpclient.netty.timeout.RequestTimeoutTimerTask.run(RequestTimeoutTimerTask.java:48)
at
io.netty.util.HashedWheelTimer$HashedWheelTimeout.expire(HashedWheelTimer.java:682)
at
io.netty.util.HashedWheelTimer$HashedWheelBucket.expireTimeouts(HashedWheelTimer.java:757)
at
io.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:485)
at java.base/java.lang.Thread.run(Thread.java:834)
jun. 12, 2019 1:13:33 P.M.
org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit$AhcWebSocketWrappedOutputStream
connect SEVERE: unable to connect
java.util.concurrent.ExecutionException:
java.util.concurrent.TimeoutException: Request timeout to
not-connected after 60000 ms at
java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395)
at
java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1999)
at
org.asynchttpclient.netty.NettyResponseFuture.get(NettyResponseFuture.java:172)
at
org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit$AhcWebSocketWrappedOutputStream.connect(AhcWebSocketConduit.java:309)
at
org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit$AhcWebSocketWrappedOutputStream.setupWrappedStream(AhcWebSocketConduit.java:167)
at
org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1343)
at
org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1304)
at
org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
at
org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:69)
at
org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1356)
at
org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit$AhcWebSocketWrappedOutputStream.close(AhcWebSocketConduit.java:139)
at
org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
I have absolutly no idea why. When I try to connect via websocket chrome client on the URL. It says success. At the same time when connecting via the client it says Timeout.
Aproach 2.
I decided to cheat CXF and provide a handmade Websocket endpoint that will be used as a front to the CXF webservice. The idea is that the Client will send a message via websocket the message will be unwrapped and then sent over CXF. This aproach is very similar to the aproach here but here it uses JMS as transport
https://github.com/pbielicki/soap-websocket-cxf
In oprder to do this I created the following Websocket enpoint:
#ServerEndpoint("/jaxWSFront")
public class JaxWSFrontEnd {
#OnOpen
public void onOpen(final Session session) {
System.out.println("Hellooo");
}
#OnMessage
public void onMessage(String mySoapMessage,final Session session) throws Exception{
// The goal here is to get the soap message and redirect it via SOAP web //service. The JaxWSFacade acts as a point that understands websocket and then //gets the soap content and sends it to enpoint that understands SOAP.
session.getBasicRemote().sendText("Helllo . Now you see me.");
System.out.println("Hellooo again");
}
#OnClose
public void onClose(Session session, CloseReason closeReason) {
System.out.println("Hellooo");
}
#OnError
public void onError(Throwable t, Session session) {
System.out.println("Hellooo");
}
}
Now I pointed my Client proxy to the jaxWsFrontEnd instead of the webservice endpoint. My expectation is that I will recieve the SOAP message in the onMessage method and then I will be able to forwards to SOAP to the CXF web service.
Now my code looks like this:
server = new Server(8088);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath( "/" );
server.setHandler(context);
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(JaxWSFrontEnd.class);
server.setHandler( context );
server.start();
Endpoint endpoint = Endpoint.create(new MyHelloWorldServicePortType() {
#Override
public String sayHello(HelloMessage message) throws FaultMessage {
return message.sayHello();
}
};
((org.apache.cxf.jaxws.EndpointImpl)endpoint).getFeatures().add(new
WSAddressingFeature());
URL wsdlDocumentLocation = new URL("file:/path to wsdl file");
String servicePart = "MyHelloWorldService";
String namespaceURI = "mynamespaceuri";
QName serviceQN = new QName(namespaceURI, servicePart);
Service service = Service.create(wsdlDocumentLocation, serviceQN);
MyHelloWorldServicePortType port = service.getPort( MyHelloWorldServicePortType.class);
portType.sayHello(new HelloMessage("Say Hello"));
For the second aproach I had in addition to the aproach 1 the following dependencies:
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-common</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-server-impl</artifactId>
</dependency>
Result from aproach 2 is absolutly the same as Aproach 1 the exceptions I recieve are the same, with one minor difference. When I use the the Chrome websocket client and point it directly the the jaxWsFrontend I am able to successfuly send a message. Why I am not able to connect to websocket wia the CXF websocket transport mechanisms ???? What am I doing wrong ?
UPDATE: enabling the loging from NETTY. It apears that netty has thrown java.lang.NoSuchMethodError: io.netty.channel.DefaultChannelId.newInstance()Lio/netty/channel/DefaultChannelId;
Maybe I have a version compatability issue with netty. The version I can see is imported in the project is 4.1.33. It is a transitive dependency I don|t have it declared.
Ok I actualy managed to crack it alone. I will post the answer for completion. Apparantly CXF guys should update their documentation IMO. On their website it is stated that in order to enable Websocket as transport protocol we need
cxf-rt-transports-websocket dependency.
What they do not say is that you in addition need async-http-client not any version but 2.0.39 a prettey old one. The problem is that it automaticaly includes transitive dependencies to netty 4.1 and the error specified above begins to manifest. What you actualy need is nett 4.0.56
Here is the fragment that made the things work for me:
<dependency>
<groupId>org.asynchttpclient</groupId>
<artifactId>async-http-client</artifactId>
<version>2.0.39</version>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-common</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.56.Final</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-websocket</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.3.2</version>
</dependency>
Aproach 1 is working
Aproach 2 I managed to trigger the onConnect event, the onMessage timedout, but in my opinion it should work I am missing something small. Anyway I don|t have more time to spent and I am happy with Aproach 1.

Categories

Resources