Fault tolerance #Asynchronous on MicroProfile REST client cause open liberty core dump on windows - open-liberty

Fault tolerance #Asynchronous-annotation on a REST client cause a core dump on Windows and the following error on MacOS:
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at ./src/java.instrument/share/native/libinstrument/JPLISAgent.c line: 873
Affected version: (Open Liberty 20.0.0.6/wlp-1.0.41.cl200620200528-0414) on OpenJDK 64-Bit Server VM, version 11.0.8+10-LTS
Used features:
[appSecurity-3.0, beanValidation-2.0, cdi-2.0, concurrent-1.0, distributedMap-1.0, ejbLite-3.2, el-3.0, jaxb-2.2, jaxrs-2.1, jaxrsClient-2.1, jdbc-4.2, jndi-1.0, jpa-2.2, jpaContainer-2.2, json-1.0, jsonb-1.0, jsonp-1.1, monitor-1.0, mpConfig-1.4, mpFaultTolerance-2.1, mpHealth-2.2, mpMetrics-2.3, mpOpenAPI-1.1, mpRestClient-1.4, requestTiming-1.0, servlet-4.0, ssl-1.0, transportSecurity-1.0].
To re-produce:
#ApplicationScoped
#RegisterRestClient(baseUri = "https://postman-echo.com")
public interface TestingClient {
#GET
#Asynchronous
#Path("delay/4")
#Consumes(value = MediaType.APPLICATION_JSON)
CompletionStage<Response> doesItCrashWithDelay(String dummyData);
Inject it:
#Inject
#RestClient
private TestingClient testingClient;
Use it:
#GET
#Path("doesitcrash")
public void doesItCrash() {
final Response response = testingClient.doesItCrashWithDelay("dummydata").toCompletableFuture().join();
logger.info(response.readEntity(String.class));
}
Workaround is to have another CDI bean invoking the rest client which have the fault tolerance annotations. But according to this blog post the REST client interface should be able to have fault tolerance annotations:
https://openliberty.io/blog/2020/06/04/asynchronous-programming-microprofile-fault-tolerance.html
Are #Asynchronous allowed on REST client that is already async due to CompletionStage? As mentioned, all other annotations like #Timeout and #Retry seems to work.

First, you are 100% correct that you don't need the #Asynchronous annotation on the MP Rest Client interface method - per the MP Rest Client specification, a return type of CompletionStage makes it asynchronous. If you remove the #Asynchronous annotation, it should work.
While investigating the JVM error message, I came across this helpful post that indicates that this message means the JVM encountered a super large exception - probably a StackOverflowError. My guess is that the error occurred because there are now two different asynchronous mechanisms (MP Rest Client and MP Fault Tolerance) playing together - and probably not playing nicely. Without seeing the exception stack trace, we won't know for sure.
I would first suggest removing the annotation and verifying that that works - that is probably a better workaround than using a separate CDI bean. Next, I would suggest opening an issue at https://github.com/OpenLiberty/open-liberty/issues to investigate a better overall solution.

Related

How can I catch the ProvisioningException that can occur when Spring kafka cannot connect to Producer endpoint?

How can I catch the ProvisioningException that can occur when Spring kafka cannot connect to Producer endpoint during Spring-Boot initialization phase?
I am using the lib called spring-cloud-stream, or in my case, more specifically: spring-cloud-starter-stream-kafka .
I assume there must be a way to define a config-Bean, or AOP, that might be able to catch the null error thrown due to connection problems? The existing error is not informative enough when connectivity is gone:
Caused by: java.util.concurrent.TimeoutException: null
at org.apache.kafka.common.internals.KafkaFutureImpl$SingleWaiter.await(KafkaFutureImpl.java:108)
at org.apache.kafka.common.internals.KafkaFutureImpl.get(KafkaFutureImpl.java:272)
at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.createTopicAndPartitions(KafkaTopicProvisioner.java:355)
at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.createTopicIfNecessary(KafkaTopicProvisioner.java:329)
at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.createTopic(KafkaTopicProvisioner.java:306)
I'm talking about the "Bean Creation Phases" documented here: https://reflectoring.io/spring-bean-lifecycle/ which describes how to hook your own code to initialization phases but I want to hook 3rd party code.
NOTE: The bounty is expired. An answer outside of the context of Spring Kafka is ok the answer is still relevant to my question.
NOTE: I found another question that also does not provide a good answer: Spring - catch bean creation exception
you can for example Capture that in ExcepcionHander
#ControllerAdvice
#RestController
public class ExceptionHandler {
#ExceptionHandler(value = {ProvisioningException.class})
public void handleException(ProvisioningExceptione) {
....code....
}
I mean the main paoint is to know when do you get this error....
when invoking a method the method should throw it but instead if it is on the initializacion or something like that, it is diferent. I can see such information in your question, please be more specific

What exceptions can be thrown by exchange() on WebClient?

I've implemented a service which makes ReST calls out to other services to implement part of its functionality. I'm using the reactive WebClient for this, something like:
webClient.post()
.uri(....)
.contentType(....)
.accept(....)
.header(....)
.syncBody(someRequestObject)
.exchange()
.flatMap(someResponseHandler::handleResponse)
.doOnError(throwable -> {
// do interesting things depending on throwable
})
.retry(1, this::somePredicateDependingOnThrowable);
Now... I handle HTTP statuses in someResponseHandler::handleResponse, but what I really want to know is, what other kinds of exception/error to expect from the exchange() - i.e.
what exceptions/errors do I get if I can't connect to the downstream service at all?
What exceptions/errors do I get if the connection attempt times out?
What exceptions/errors do I get if I can connect but then the request times out before I get a response?
None of these are HTTP status codes, obviously - but I can't find any documentation to tell me what I can look for. Am I just not looking in the right places? I've had a look through the documentation for the reactive WebClient, and I've had a look through the Reactor Netty Reference Guide, but no luck.
For background, this is important because we do HATEOAS-based service discovery - for some of these exceptions, I want to trigger rediscovery, for some of them, I don't.
I recommend testing your code that uses the WebClient to see how it handles the various scenarios you mentioned. You can test your code against something like MockWebServer easily from unit tests. MockWebServer can simulate most of the errors mentioned here.
Having said that, here's what I have seen in my testing when using WebClient with the ReactorClientHttpConnector. Other connectors may throw slightly different exceptions, but will likely share a super class in the exception class hierarchy as those mentioned below.
Unknown host
java.net.UnknownHostException
Connection refused (port not open on server)
java.net.ConnectException (or subclass)
reactor-netty throws io.netty.channel.AbstractChannel$AnnotatedConnectException
Connect timeout
If you have configured a connect timeout, then you will receive java.net.ConnectException (or subclass)
reactor-netty throws io.netty.channel.ConnectTimeoutException
SSL handshake errors
javax.net.ssl.SSLHandshakeException (or subclass)
Request body encoding error
This varies by the encoder being used, but generally will be org.springframework.core.codec.EncodingException (or subclass)
Some encoders also throw java.lang.IllegalStateException if encoding is configured incorrectly
Response body decoding error
This varies by the decoder being used, but generally will be org.springframework.core.codec.DecodingException (or subclass)
Some decoders also throw java.lang.IllegalStateException if decoding is configured incorrectly
Read Timeout
If using reactor-netty, and you configured a io.netty.handler.timeout.ReadTimeoutHandler, then io.netty.handler.timeout.ReadTimeoutException
If you use the .timeout operator somewhere in the reactive stream call chain, then java.util.concurrent.TimeoutException
Write Timeout
If using reactor-netty, and you configured a io.netty.handler.timeout.WriteTimeoutHandler, then io.netty.handler.timeout.WriteTimeoutException
Connection closed by server prematurely (before response completes)
java.io.IOException (or subclass)
reactor-netty throws reactor.netty.http.client.PrematureCloseException
Others
Any exceptions that occur during your someResponseHandler::handleResponse

Jersey Exception Java 1.8

I am calling a REST service and the provider has supplied a client. Client's specification is to use Jersey 2.18. So i have used the below jersey dependencies
Jersey-client-2.18.jar
Jersey-common-2.18.jar
Jersey-entity-filtering-2.18.jar
Jersey-guava-2.18.jar
jersey-media-json-jackson-2.18.jar
I am making calls using scheduledThreadPoolExecutor and my application is running in tc server and JDK 1.8. Sporadically i get the below exception. I tried searching this exception in google but no luck. But i see the below for almost everytime
Cannot create new registration for component type class > org.glassfish.jersey.client.authentication.HttpAuthenticationFeature
Exception
java.lang.NullPointerException at
org.glassfish.jersey.model.internal.CommonConfig.configureFeatures(CommonConfig.java:694)
at
org.glassfish.jersey.model.internal.CommonConfig.configureMetaProviders(CommonConfig.java:644)
at
org.glassfish.jersey.client.ClientConfig$State.configureMetaProviders(ClientConfig.java:365)
at
org.glassfish.jersey.client.ClientConfig$State.initRuntime(ClientConfig.java:398)
at
org.glassfish.jersey.client.ClientConfig$State.access$000(ClientConfig.java:88)
at
org.glassfish.jersey.client.ClientConfig$State$3.get(ClientConfig.java:120)
at
org.glassfish.jersey.client.ClientConfig$State$3.get(ClientConfig.java:117)
at
org.glassfish.jersey.internal.util.collection.Values$LazyValueImpl.get(Values.java:340)
at
org.glassfish.jersey.client.ClientConfig.getRuntime(ClientConfig.java:726)
at
org.glassfish.jersey.client.ClientRequest.getConfiguration(ClientRequest.java:285)
at
org.glassfish.jersey.client.JerseyInvocation.validateHttpMethodAndEntity(JerseyInvocation.java:126)
at
org.glassfish.jersey.client.JerseyInvocation.(JerseyInvocation.java:98)
at
org.glassfish.jersey.client.JerseyInvocation.(JerseyInvocation.java:91)
at
org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:411)
at
org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:307)
I resolved this issue. My implementation was wrong. The client object was defined as a class level variable and it was initialized during every method call. During parallel call. every thread concurrent call attacks the same class level object and tries to modify and hence the object was not properly initialized. Now i fixed it by injecting the class from spring so that it is not modified during every call.

Spring on WebSphere 8: Quartz job with web service call throws JAXBException "<class> is not known to this context"

I'm facing a JAXBException " is not known to this context" when calling a web service from within a job controlled by Quartz on Spring:
javax.xml.ws.WebServiceException: javax.xml.bind.JAXBException: com.xxxx.yyyy.zzzz.ImageMetaData is not known to this context
at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactory.java:175)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:70)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:128)
at org.apache.axis2.jaxws.marshaller.impl.alt.DocLitWrappedMinimalMethodMarshaller.demarshalResponse(DocLitWrappedMinimalMethodMarshaller.java:624)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.createResponse(JAXWSProxyHandler.java:593)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:432)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invoke(JAXWSProxyHandler.java:213)
at com.sun.proxy.$Proxy299.findAllImageMetaData(Unknown Source)
I'm having a Spring 3.2.4 Java EE application with JSF running on IBM WebSphere v8.
When calling a specific web service from the JSF part of the application (i.e. from an action or a service), everything's ok.
The exception occurs only when the call is done from within a Quartz/Spring triggered job.
Executing exacty the same job code from the action does not result in an exception.
I tried a lot of different things like using a corresponding #XmlSeeAlso annotation in the JAXB generated classes but even using the annotation in the webservice interface itself does not solve the issue.
I also updated the Spring and Quartz libraries to more recent versions but this didn't help.
Anyone any idea?
I've finally solved the issue.
After much analysis I encountered the following issue in the Spring framework:
https://jira.spring.io/i#browse/SPR-11125
When a job is triggered via Spring/Quartz on WebSphere, the wrong ContextClassLoader is set.
This may cause many different problems - among them is the JAXBException as described.
The Spring bug is still open - so as a workaround I had to overwrite the context class loader of the current thread by the correct one:
ClassLoader cl = invoiceService.getClass().getClassLoader();
Thread.currentThread().setContextClassLoader(cl);
The correct class loader can be simply retrieved by a class that has been loaded by the container. Using this class loader as the context class loader for the current thread solved my issue.

Integrate GWT with Spring Security framework

I have searched for tutorials on this topics, but all of them are outdated. Could anyone provide to me any links, or samples about integrating Spring security into GWT?
First of all, you have to bear in mind that GWT application is turned into javascript running on client-side, so there is nothing you can really do about securing some resources out there. All sensitive information should be stored on server side (as in every other case, not only for GWT), so the right way is to think of Spring Security integration from the point of view of application services layer and integrating that security with communication protocol you use - in case of GWT it is request factory in most cases.
The solution is not very simple, but I could not do it in any better way... any refinement suggestions are welcome.
You need to start with creating GWT ServiceLayerDecorator that will connect the world of request factory with world of Spring. Overwrite createServiceInstance method taking name of spring service class to be invoked from ServiceName annotation value and return instance of this service (you need to obtain it from Spring ApplicationContext):
final Class<?> serviceClass = requestContext.getAnnotation(ServiceName.class).value();
return appContext.getBean(serviceClass);
Also, you need to override superclass invoke(Method, Object...) method in order to catch all thrown runtime exceptions.
Caught exception cause should be analyzed, if it's an instance of Spring Security AccessDeniedException. If so, exception cause should be rethrown. In such case, GWT will not serialize exception into string, but rethrow it again, thus, dispatcher servlet can handle it by setting appropriate HTTP response status code. All other types of exceptions will be serialized by GWT into String.
Actually, you could catch only GWT ReportableException, but unfortunately it has package access modifier (heh... GWT is not so easily extensible). Catching all runtime exceptions is much more safe (althouth not very elegant, we have no choice) - if GWT implementation change, this code will still work fine.
Now you need to plug in your decorator. You can do it easily by extending request factory servlet and defining your's servlet constructor as follows:
public MyRequestFactoryServlet() {
this(new DefaultExceptionHandler(), new SpringServiceLayerDecorator());
}
The last thing - you need to do a dirty hack and overwrite request factory servlet doPost method changing the way how it handles exceptions - by default, exception is serialized into string and server sends 500 status code. Not all exceptions should result in 500 s.c - for example security exceptions should result in unauthorized status code. So what you need to do is to overwrite exception handling mechanism in the following way:
catch (RuntimeException e) {
if (e instanceof AccessDeniedException) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
} else {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
LOG.log(Level.SEVERE, "Unexpected error", e);
}
}
Instead of extending classes, you can try to use some 'around' aspects - it is cleaner solution in this case.
That's it! Now you can annotate your application services layer as usual with Spring Security annotations (#Secured and so forth).
I know - it's all complicated, but Google's request factory is hardly extendable. Guys did a great work about communication protocol, but design of this library is just terrible. Of course the client-side code has some limitations (it is compiled to java script), but server-side code could be designed much better...

Resources