I'm trying to send and receive a TCP message via Citrus-Framework, where I used this thread as a reference:
Receiving messages from tcp server with Citrus framework and Spring Integration times out
I'm using a python message repeater, which returns the received message. I receive a payload with python and returns it but citrus times out. I tried all serializers (except SingleTerminatior, causes a context error).
I tried different serializers but none seem to solve my problem, Citrus always times out.
15:03:58,013 DEBUG t.TestContextFactory| Created new test context - using global variables: '{}'
15:03:58,024 INFO port.LoggingReporter|
15:03:58,024 INFO port.LoggingReporter|------------------------------------------------------------------------
15:03:58,024 DEBUG port.LoggingReporter| STARTING TEST sendSpringIntegrationMessageTest <com.consol.citrus.samples>
15:03:58,025 INFO port.LoggingReporter|
15:03:58,025 DEBUG citrus.TestCase| Initializing test case
15:03:58,026 DEBUG context.TestContext| Setting variable: citrus.test.name with value: 'sendSpringIntegrationMessageTest'
15:03:58,027 DEBUG context.TestContext| Setting variable: citrus.test.package with value: 'com.consol.citrus.samples'
15:03:58,028 DEBUG citrus.TestCase| Test variables:
15:03:58,028 DEBUG citrus.TestCase| citrus.test.name = sendSpringIntegrationMessageTest
15:03:58,028 DEBUG citrus.TestCase| citrus.test.package = com.consol.citrus.samples
15:03:58,029 INFO port.LoggingReporter|
15:03:58,030 DEBUG port.LoggingReporter| TEST STEP 1/2: send
15:03:58,049 DEBUG nnel.ChannelProducer| Sending message to channel: 'input'
15:03:58,055 DEBUG nnel.ChannelProducer| Message to send is:
DEFAULTMESSAGE [id: c5c61991-f567-42bd-9302-1f8e1fa16225, payload: Req][headers: {citrus_message_type=XML, citrus_message_id=c5c61991-f567-42bd-9302-1f8e1fa16225, citrus_message_timestamp=1539090238031}]
15:03:58,164 INFO nnel.ChannelProducer| Message was sent to channel: 'input'
15:03:58,165 INFO port.LoggingReporter|
15:03:58,166 DEBUG port.LoggingReporter| TEST STEP 1/2 SUCCESS
15:03:58,166 INFO port.LoggingReporter|
15:03:58,166 DEBUG port.LoggingReporter| TEST STEP 2/2: receive
15:03:58,168 DEBUG nnel.ChannelConsumer| Receiving message from: replies
15:04:03,171 INFO port.LoggingReporter|
15:04:03,172 ERROR port.LoggingReporter| TEST FAILED sendSpringIntegrationMessageTest <com.consol.citrus.samples> Nested exception is:
at com.consol.citrus.exceptions.ActionTimeoutException: Action timeout while receiving message from channel 'replies'
at com.consol.citrus.channel.ChannelConsumer.receive(ChannelConsumer.java:97)
at com.consol.citrus.messaging.AbstractSelectiveMessageConsumer.receive(AbstractSelectiveMessageConsumer.java:50)
at com.consol.citrus.actions.ReceiveMessageAction.receive(ReceiveMessageAction.java:141)
at com.consol.citrus.actions.ReceiveMessageAction.doExecute(ReceiveMessageAction.java:120)
at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:46)
at com.consol.citrus.dsl.actions.DelegatingTestAction.doExecute(DelegatingTestAction.java:54)
at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:46)
at com.consol.citrus.TestCase.executeAction(TestCase.java:234)
at com.consol.citrus.TestCase.doExecute(TestCase.java:153)
at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:46)
at com.consol.citrus.Citrus.run(Citrus.java:403)
at com.consol.citrus.dsl.testng.TestNGCitrusTest.invokeTestMethod(TestNGCitrusTest.java:125)
at com.consol.citrus.dsl.testng.TestNGCitrusTestDesigner.invokeTestMethod(TestNGCitrusTestDesigner.java:73)
at com.consol.citrus.dsl.testng.TestNGCitrusTest.run(TestNGCitrusTest.java:110)
...
My context seems to be right (I'm using spring-integration-ip 5.0.8-RELEASE), there is no exception when executing the test (except using SingleTerminatior):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
... >
<citrus:channel-endpoint id="citrusServiceInputEndpoint"
channel-name="input" />
<citrus:channel-endpoint id="citrusServiceRepliesEndpoint"
channel-name="replies" />
<int-ip:tcp-connection-factory id="client"
type="client" host="127.0.0.1"
port="33500" single-use="false"
so-timeout="10000" using-nio="true"
deserializer="javaSerializer"
serializer="javaSerializer" />
<bean id="javaSerializer"
class="org.springframework.integration.ip.tcp.serializer.ByteArrayLfSerializer" />
<int:channel id="input" />
<int:channel id="replies">
<int:queue />
</int:channel>
<int-ip:tcp-outbound-channel-adapter
id="outboundClient" channel="input" connection-factory="client" />
<int-ip:tcp-inbound-channel-adapter
id="inboundClient" channel="replies" connection-factory="client" />
</beans>
I appreciate any kind of help
Thanks
because I'm new to spring here is the dependency I added from my part:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-ip</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
This is the debug output of citrus:
22:47:41,071 DEBUG port.LoggingReporter| TEST STEP 1/2: send
22:47:41,085 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'citrusServiceInputEndpoint'
22:47:41,086 DEBUG nnel.ChannelProducer| Sending message to channel: 'input'
22:47:41,086 DEBUG nnel.ChannelProducer| Message to send is:
DEFAULTMESSAGE [id: 7d4f4c7a-92d0-462c-b695-c32fc7e697ae, payload: Req][headers: {citrus_message_type=XML, citrus_message_id=7d4f4c7a-92d0-462c-b695-c32fc7e697ae, citrus_message_timestamp=1539118061073}]
22:47:41,087 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'input'
22:47:41,091 DEBUG hannel.DirectChannel| preSend on channel 'input', message:
GenericMessage [payload=Req, headers={citrus_message_timestamp=1539118061073, citrus_message_type=XML, id=33295f63-948f-6bcf-289f-d5e1df8dc98b, citrus_message_id=7d4f4c7a-92d0-462c-b695-c32fc7e697ae, timestamp=1539118061091}]
22:47:41,092 DEBUG endingMessageHandler| org.springframework.integration.ip.tcp.TcpSendingMessageHandler#0 received message:
GenericMessage [payload=Req, headers={citrus_message_timestamp=1539118061073, citrus_message_type=XML, id=33295f63-948f-6bcf-289f-d5e1df8dc98b, citrus_message_id=7d4f4c7a-92d0-462c-b695-c32fc7e697ae, timestamp=1539118061091}]
22:47:41,092 DEBUG entConnectionFactory| Opening new socket connection to 127.0.0.1:33500
22:47:41,106 DEBUG ion.TcpNioConnection| New connection localhost:33500:55108:33be3b24-f5ae-4594-83e9-c7eb0f104b1f
22:47:41,110 DEBUG entConnectionFactory| client: Added new connection: localhost:33500:55108:33be3b24-f5ae-4594-83e9-c7eb0f104b1f
22:47:41,113 DEBUG endingMessageHandler| Got Connection localhost:33500:55108:33be3b24-f5ae-4594-83e9-c7eb0f104b1f
22:47:41,114 DEBUG ion.TcpNioConnection| localhost:33500:55108:33be3b24-f5ae-4594-83e9-c7eb0f104b1f writing 4
22:47:41,116 DEBUG ion.TcpNioConnection| localhost:33500:55108:33be3b24-f5ae-4594-83e9-c7eb0f104b1f Message sent GenericMessage [payload=Req, headers={citrus_message_timestamp=1539118061073, citrus_message_type=XML, id=33295f63-948f-6bcf-289f-d5e1df8dc98b, citrus_message_id=7d4f4c7a-92d0-462c-b695-c32fc7e697ae, timestamp=1539118061091}]
22:47:41,117 DEBUG channel.DirectChannel| postSend (sent=true) on channel 'input', message: GenericMessage [payload=Req, headers={citrus_message_timestamp=1539118061073, citrus_message_type=XML, id=33295f63-948f-6bcf-289f-d5e1df8dc98b, citrus_message_id=7d4f4c7a-92d0-462c-b695-c32fc7e697ae, timestamp=1539118061091}]
22:47:41,118 INFO nnel.ChannelProducer| Message was sent to channel: 'input'
22:47:41,118 INFO port.LoggingReporter|
22:47:41,119 DEBUG port.LoggingReporter| TEST STEP 1/2 SUCCESS
22:47:41,119 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'citrusServiceRepliesEndpoint'
22:47:41,120 INFO port.LoggingReporter|
22:47:41,121 DEBUG port.LoggingReporter| TEST STEP 2/2: receive
22:47:41,122 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'citrusServiceRepliesEndpoint'
22:47:41,124 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'response'
22:47:41,125 DEBUG nnel.ChannelConsumer| Receiving message from: response
22:47:46,130 INFO port.LoggingReporter|
22:47:46,131 ERROR port.LoggingReporter| TEST FAILED
sendSpringIntegrationMessageTest <com.consol.citrus.samples> Nested exception is:
com.consol.citrus.exceptions.ActionTimeoutException: Action timeout while receiving message from channel 'response'
...
I checked Wireshark and the payload ("Req") inclusive the linefeed was returned, which can be seen in the screenshot. Maybe I should mention I'm running this in an Ubuntu VM.
Wireshark screenshot
#CitrusTest(name = "sendSpringIntegrationMessageTest")
public void sendSpringIntegrationMessageTest() throws Exception {
send("citrusServiceInputEndpoint").payload("Req");
receive("citrusServiceRepliesEndpoint").payload("Req");
}
EDIT
ok there seem to be an issue in my python server. I changed the code a bit to see the received bytes on the console (before I was just counting the bytes) and suddenly the output of citrus changed.
11:40:54,924 DEBUG port.LoggingReporter| TEST STEP 2/2: receive
11:40:54,925 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'citrusServiceRepliesEndpoint'
11:40:54,925 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'response'
11:40:54,925 DEBUG nnel.ChannelConsumer| Receiving message from: response
11:40:54,928 DEBUG ion.TcpNioConnection| localhost:33500:55890:7537f5ed-f447-4b76-ba66-2ec59c7619a9 Reading...
11:40:54,929 DEBUG ion.TcpNioConnection| localhost:33500:55890:7537f5ed-f447-4b76-ba66-2ec59c7619a9 Running an assembler
11:40:54,929 DEBUG ion.TcpNioConnection| Read 4 into raw buffer
Exception in thread "pool-1-thread-3" java.lang.AbstractMethodError: org.springframework.integration.ip.tcp.connection.TcpMessageMapper.toMessage(Ljava/lang/Object;)Lorg/springframework/messaging/Message;
at org.springframework.integration.ip.tcp.connection.TcpNioConnection.convert(TcpNioConnection.java:358)
at org.springframework.integration.ip.tcp.connection.TcpNioConnection.run(TcpNioConnection.java:235)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
11:40:54,937 DEBUG ion.TcpNioConnection| localhost:33500:55890:7537f5ed-f447-4b76-ba66-2ec59c7619a9 Reading...
11:40:54,938 DEBUG ion.TcpNioConnection| Read 0 into raw buffer
11:40:59,930 INFO port.LoggingReporter|
11:40:59,931 ERROR port.LoggingReporter| TEST FAILED sendSpringIntegrationMessageTest <com.consol.citrus.samples> Nested exception is:
com.consol.citrus.exceptions.ActionTimeoutException: Action timeout while receiving message from channel 'response'
EDIT2
Because of the following post:
How to use Spring Integration 5 with Spring Boot 1.5.x
I switched from spring-integration-ip 5.0.8 to 4.3.9 and there the output changed one more time. Now my problem seems to move away from TCP issues to actual spring know-how.
15:04:12,318 DEBUG port.LoggingReporter| TEST STEP 2/2: receive
15:04:12,319 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'citrusServiceRepliesEndpoint'
15:04:12,319 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'replies'
15:04:12,319 DEBUG nnel.ChannelConsumer| Receiving message from: replies
15:04:12,327 DEBUG ion.TcpNioConnection| localhost:33500:56004:1174f4c6-608c-44c6-aeec-33da4074e195 Reading...
15:04:12,328 DEBUG ion.TcpNioConnection| localhost:33500:56004:1174f4c6-608c-44c6-aeec-33da4074e195 Running an assembler
15:04:12,329 DEBUG ion.TcpNioConnection| Read 4 into raw buffer
15:04:12,329 DEBUG ion.TcpNioConnection| localhost:33500:56004:1174f4c6-608c-44c6-aeec-33da4074e195 Reading...
15:04:12,330 DEBUG ion.TcpNioConnection| Read 0 into raw buffer
15:04:12,332 DEBUG yteArrayLfSerializer| Available to read:4
15:04:12,333 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'messageBuilderFactory'
15:04:12,336 DEBUG channel.QueueChannel| preSend on channel 'replies', message: GenericMessage [payload=byte[3], headers={ip_tcp_remotePort=33500, ip_connectionId=localhost:33500:56004:1174f4c6-608c-44c6-aeec-33da4074e195, ip_localInetAddress=0.0.0.0/0.0.0.0, ip_address=127.0.0.1, id=9bd90a54-cc2b-d3d0-ca63-6355f53dee7c, ip_hostname=localhost, timestamp=1539176652336}]
15:04:12,339 DEBUG channel.QueueChannel| postReceive on channel 'replies', message: GenericMessage [payload=byte[3], headers={ip_tcp_remotePort=33500, ip_connectionId=localhost:33500:56004:1174f4c6-608c-44c6-aeec-33da4074e195, ip_localInetAddress=0.0.0.0/0.0.0.0, ip_address=127.0.0.1, id=9bd90a54-cc2b-d3d0-ca63-6355f53dee7c, ip_hostname=localhost, timestamp=1539176652336}]
15:04:12,340 DEBUG nnel.ChannelConsumer| Received message from: replies
15:04:12,340 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'citrusServiceRepliesEndpoint'
15:04:12,354 DEBUG channel.QueueChannel| postSend (sent=true) on channel 'replies', message: GenericMessage [payload=byte[3], headers={ip_tcp_remotePort=33500, ip_connectionId=localhost:33500:56004:1174f4c6-608c-44c6-aeec-33da4074e195, ip_localInetAddress=0.0.0.0/0.0.0.0, ip_address=127.0.0.1, id=9bd90a54-cc2b-d3d0-ca63-6355f53dee7c, ip_hostname=localhost, timestamp=1539176652336}]
15:04:12,379 INFO port.LoggingReporter|
15:04:12,381 ERROR port.LoggingReporter| TEST FAILED sendSpringIntegrationMessageTest <com.consol.citrus.samples> Nested exception is:
com.consol.citrus.exceptions.CitrusRuntimeException: Could not find proper message validator for message type 'XML', please define a capable message validator for this message type
EDIT3
Seems like after adjusting my environment a lot for test, I was lastly missing this line in my context file:
<int:object-to-string-transformer id="transformer" input-channel="replies" output-channel="response" />
Thanks for nudging me into the right direction.
Related
I'm trying to improve the error handling in a controller by using the #Error annotation.
#Get(uri = "/{id}")
#Secured("ROLE_VIEW")
HttpResponse<AuthorResource> show(Long id) {
try {
ok(authorService.get(id).get())
} catch (Exception e) {
e.printStackTrace()
throw e
}
}
The get() method will either return the AuthorResource (io.vavr.control.Try), or throw a custom exception, subclass of our base ErrorContext exception class.
I then added the following errorhandler in the controller:
#Error(exception = ErrorContext, global = true)
HttpResponse<ErrorContext> onErrorContext(HttpRequest request, ErrorContext error) {
HttpResponse.<ErrorContext>status(HttpStatus.valueOf(error.code)).body(error)
}
Unfortunately, the exception handler does not seem to be invoked, and an INTERNAL_SERVER_ERROR is triggered (instead of a NOT_FOUND in this example). The output of the gradle test task can be found below.
I have tried the following:
Using a global handler (global=true)
Annotating the handler with the actual subclass that is being thrown (ErrorContextWithoutStacktrace)
Am I missing anything?
I have created a working application in github here
Controller class
Test class
Output of test (including partial stacktraces due to length limitation in SO):
10:50:31.455 [ForkJoinPool.commonPool-worker-7] INFO i.m.t.e.TestResourcesResolverLoader - Loaded 1 test resources resolvers: io.micronaut.testresources.testcontainers.GenericTestContainerProvider
10:50:31.579 [main] INFO i.m.testresources.server.Application - A Micronaut Test Resources server is listening on port 43207, started in 182ms
10:50:33.164 [default-nioEventLoopGroup-1-2] INFO i.m.t.e.TestResourcesResolverLoader - Loaded 1 test resources resolvers: io.micronaut.testresources.testcontainers.GenericTestContainerProvider
> Task :test
AuthorControllerSpec STANDARD_OUT
10:50:32.581 [Test worker] INFO i.m.context.env.DefaultEnvironment - Established active environments: [test]
10:50:33.131 [multithreadEventLoopGroup-1-1] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP GET to http://localhost:43207/requirements/entries
10:50:33.190 [multithreadEventLoopGroup-1-1] DEBUG i.m.h.client.netty.DefaultHttpClient - Received response 200 from http://localhost:43207/requirements/entries
10:50:33.216 [multithreadEventLoopGroup-1-2] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP POST to http://localhost:43207/list
10:50:33.246 [multithreadEventLoopGroup-1-2] DEBUG i.m.h.client.netty.DefaultHttpClient - Received response 200 from http://localhost:43207/list
10:50:33.249 [multithreadEventLoopGroup-1-3] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP GET to http://localhost:43207/requirements/entries
10:50:33.254 [multithreadEventLoopGroup-1-3] DEBUG i.m.h.client.netty.DefaultHttpClient - Received response 200 from http://localhost:43207/requirements/entries
10:50:33.258 [multithreadEventLoopGroup-1-4] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP POST to http://localhost:43207/list
10:50:33.262 [multithreadEventLoopGroup-1-4] DEBUG i.m.h.client.netty.DefaultHttpClient - Received response 200 from http://localhost:43207/list
10:50:33.367 [Test worker] INFO i.m.c.h.g.HibernateDatastoreFactory - Starting GORM for Hibernate
10:50:33.883 [Test worker] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 5.6.11.Final
10:50:33.984 [Test worker] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 6.2.5.Final
10:50:34.074 [Test worker] INFO o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
10:50:34.139 [Test worker] INFO org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
AuthorControllerSpec > It fails to get an non-existing Author > example.controller.AuthorControllerSpec.It fails to get an non-existing Author [badId: 546252431, #0] STANDARD_OUT
10:50:34.879 [default-nioEventLoopGroup-3-2] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP GET to http://localhost:37361/author/546252431
AuthorControllerSpec > It fails to get an non-existing Author > example.controller.AuthorControllerSpec.It fails to get an non-existing Author [badId: 546252431, #0] STANDARD_ERROR
error.ErrorContextWithoutStacktrace: Author with id 546252431 not found.
AuthorControllerSpec > It fails to get an non-existing Author > example.controller.AuthorControllerSpec.It fails to get an non-existing Author [badId: 546252431, #0] STANDARD_OUT
10:50:34.999 [default-nioEventLoopGroup-3-3] ERROR i.m.http.server.RouteExecutor - Unexpected error occurred: Required argument [HttpRequest request] not specified
io.micronaut.web.router.exceptions.UnsatisfiedRouteException: Required argument [HttpRequest request] not specified
at io.micronaut.web.router.exceptions.UnsatisfiedRouteException.create(UnsatisfiedRouteException.java:76)
at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:297)
at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:111)
at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:103)
at io.micronaut.http.server.RouteExecutor.lambda$executeRoute$14(RouteExecutor.java:659)
at reactor.core.publisher.FluxDeferContextual.subscribe(FluxDeferContextual.java:49)
[Skipped a lot of reactive frames]
at reactor.core.publisher.Flux.subscribe(Flux.java:8522)
at io.micronaut.http.server.netty.RoutingInBoundHandler.handleRouteMatch(RoutingInBoundHandler.java:601)
at io.micronaut.http.server.netty.RoutingInBoundHandler.channelRead0(RoutingInBoundHandler.java:457)
at io.micronaut.http.server.netty.RoutingInBoundHandler.channelRead0(RoutingInBoundHandler.java:147)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
[Skipped a lot of netty channel stuff]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
10:50:35.031 [default-nioEventLoopGroup-3-2] DEBUG i.m.h.client.netty.DefaultHttpClient - Received response 500 from http://localhost:37361/author/546252431
10:50:35.049 [Test worker] ERROR i.m.r.intercept.RecoveryInterceptor - Type [example.controller.Api$Intercepted] executed with error: error.ErrorResource#475fb7
io.micronaut.http.client.exceptions.HttpClientResponseException: error.ErrorResource#475fb7
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.makeErrorFromRequestBody(DefaultHttpClient.java:2226)
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.buildResponse(DefaultHttpClient.java:2199)
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.buildResponse(DefaultHttpClient.java:2122)
at io.micronaut.http.client.netty.DefaultHttpClient$BaseHttpResponseHandler.channelReadInstrumented(DefaultHttpClient.java:2097)
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.channelReadInstrumented(DefaultHttpClient.java:2158)
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.channelReadInstrumented(DefaultHttpClient.java:2122)
at io.micronaut.http.client.netty.SimpleChannelInboundHandlerInstrumented.channelRead0(SimpleChannelInboundHandlerInstrumented.java:49)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
[Skipped a lot of netty channel stuff]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99)
at reactor.core.publisher.Flux.blockFirst(Flux.java:2600)
at io.micronaut.http.client.netty.DefaultHttpClient$1.exchange(DefaultHttpClient.java:498)
at io.micronaut.http.client.netty.DefaultHttpClient$1.retrieve(DefaultHttpClient.java:505)
at io.micronaut.http.client.interceptor.HttpClientIntroductionAdvice.lambda$intercept$5(HttpClientIntroductionAdvice.java:409)
at io.micronaut.http.client.interceptor.HttpClientIntroductionAdvice.handleBlockingCall(HttpClientIntroductionAdvice.java:508)
at io.micronaut.http.client.interceptor.HttpClientIntroductionAdvice.intercept(HttpClientIntroductionAdvice.java:408)
at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:137)
at io.micronaut.retry.intercept.RecoveryInterceptor.intercept(RecoveryInterceptor.java:92)
at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:137)
at example.controller.Api$Intercepted.getAuthor(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap.invoke(PojoMetaMethodSite.java:203)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
at example.controller.AuthorControllerSpec.$spock_feature_0_0(AuthorControllerSpec.groovy:33)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:198)
[Skipped a lot of gradle, junit, and spock stuff]
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
AuthorControllerSpec > It fails to get an non-existing Author > example.controller.AuthorControllerSpec.It fails to get an non-existing Author [badId: 546252431, #0] FAILED
org.spockframework.runtime.SpockComparisonFailure at AuthorControllerSpec.groovy:37
You imported the wrong HttpRequest
Instead of import java.net.http.HttpRequest you should import import io.micronaut.http.HttpRequest.
But even then you will not catch HttpClientResponseException because you don't use any Client in your test. If you want to receive this exception you should write something like this:
#Inject
#Client("/author")
HttpClient client
#IgnoreRest
def "It fails to get an non-existing Author with an HttpClient"() {
given:
def token = viewer()
when:
def author = client.toBlocking().exchange(HttpRequest.create(
HttpMethod.GET,
"/" + badId
).bearerAuth(token))
then:
def ex = thrown(HttpClientResponseException)
ex.status == NOT_FOUND
ex.getResponse().getBody(ErrorResource).map {
assert it.message == "Author with id ${badId} not found."
it
}.isPresent()
where:
badId = anyInt()
}
My Java Spring Authentication and Authorization Server is working.
I want to solve the errors in the requests I send from a client according to the OAuth2 flow. But none of the errors I get are detailed. For example, this request sent to /oauth2/authorize:
https://MY_DOMAIN/authorize?
response_type=code&
client_id=MY_CLIENT_ID&
redirect_uri=MY_CALLBACK_URL&
scope=SCOPE&
state=STATE
Gives the following error after I enter credentials:
My goal is not to resolve the error here, but there are different errors I get like this and I need to see a more informative error message so I can debug them all.
The console also has a non-informative output that goes like this:
...
2022-08-15 15:52:33.739 DEBUG 50827 --- [nio-9000-exec-4] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
2022-08-15 15:52:33.739 DEBUG 50827 --- [nio-9000-exec-4] o.a.c.c.C.[Tomcat].[localhost] : Processing ErrorPage[errorCode=0, location=/error]
2022-08-15 15:52:33.739 DEBUG 50827 --- [nio-9000-exec-4] o.s.security.web.FilterChainProxy : Securing GET /error?protocol=oauth2&response_type=code&access_type&client_id=articles-client&redirect_uri=http%3A%2F%2F127.0.0.1%3A3000%2Flms%2Flogin&scope=openid%20articles.read&state=XqqDv6wx6O&code_challenge_method=plain&code_challenge=e964fe0c4b609ef3cf29658efc6077e7feb591f78c458c2092aa56c9
...
I'm trying to use Citrus to build a configurable mockup that I'd like to run from the command line passing different parameters to the test each time I run it.
I tried to use this as a reference to get started https://github.com/citrusframework/citrus/issues/325 but could not get it to work in my case.
I've got a running test running with one test case inside and I can run it like that
mvn clean verify -Dit.test=myTest#myTestCase
But when trying to run the following app:
package com.grge.citrus;
import com.consol.citrus.dsl.design.DefaultTestDesigner;
import com.consol.citrus.Citrus;
import com.consol.citrus.context.TestContext;
import org.springframework.context.ConfigurableApplicationContext;
import com.grge.citrus.*;
import com.consol.citrus.dsl.testng.TestNGCitrusTestDesigner;
public class App {
public static void main(String[] args) {
String suiteName = "mySuite";
Citrus citrus = Citrus.newInstance();
// my test with one testcase inside
TestNGCitrusTestDesigner myTest = new MyTest();
try {
citrus.beforeSuite(suiteName);
// This works it come from the sample
citrus.run(new SampleJavaDslTest().getTestCase());
// fails null pointer exception
citrus.run(myTest.getTestCase());
citrus.afterSuite(suiteName);
} finally {
((ConfigurableApplicationContext) citrus.getApplicationContext()).close();
}
}
private static class SampleJavaDslTest extends DefaultTestDesigner {
public SampleJavaDslTest() {
super();
echo("Hello from Java DSL!");
}
}
}
It fails with the following error
22:08:21,691 DEBUG citrus.Citrus| Loading Citrus application properties
22:08:21,696 DEBUG citrus.Citrus| Setting application property citrus.spring.java.config=com.grge.citrus.VCenterActorConfigSSL
22:08:22,025 DEBUG BeanDefinitionReader| Loaded 0 bean definitions from location pattern [classpath*:citrus-context.xml]
22:08:23,059 DEBUG server.HttpServer| Starting server: vCenterServer ...
22:08:23,217 DEBUG CachingServletFilter| Initializing filter 'request-caching-filter'
22:08:23,220 DEBUG CachingServletFilter| Filter 'request-caching-filter' configured successfully
22:08:23,220 DEBUG et.GzipServletFilter| Initializing filter 'gzip-filter'
22:08:23,220 DEBUG et.GzipServletFilter| Filter 'gzip-filter' configured successfully
22:08:23,222 DEBUG rusDispatcherServlet| Initializing servlet 'vCenterServer-servlet'
22:08:23,241 INFO rusDispatcherServlet| FrameworkServlet 'vCenterServer-servlet': initialization started
22:08:23,250 DEBUG rusDispatcherServlet| Servlet with name 'vCenterServer-servlet' will try to create custom WebApplicationContext context of class 'org.springframework.web.context.support.XmlWebApplicationContext', using parent context [null]
22:08:23,865 DEBUG rusDispatcherServlet| Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided
22:08:23,869 DEBUG rusDispatcherServlet| Unable to locate LocaleResolver with name 'localeResolver': using default [org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver#16fb356]
22:08:23,873 DEBUG rusDispatcherServlet| Unable to locate ThemeResolver with name 'themeResolver': using default [org.springframework.web.servlet.theme.FixedThemeResolver#1095f122]
22:08:23,894 DEBUG rusDispatcherServlet| No HandlerExceptionResolvers found in servlet 'vCenterServer-servlet': using default
22:08:23,896 DEBUG rusDispatcherServlet| Unable to locate RequestToViewNameTranslator with name 'viewNameTranslator': using default [org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator#733c423e]
22:08:23,910 DEBUG rusDispatcherServlet| No ViewResolvers found in servlet 'vCenterServer-servlet': using default
22:08:23,915 DEBUG rusDispatcherServlet| Unable to locate FlashMapManager with name 'flashMapManager': using default [org.springframework.web.servlet.support.SessionFlashMapManager#681aad3b]
22:08:23,922 DEBUG rusDispatcherServlet| Published WebApplicationContext of servlet 'vCenterServer-servlet' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.vCenterServer-servlet]
22:08:23,922 INFO rusDispatcherServlet| FrameworkServlet 'vCenterServer-servlet': initialization completed in 678 ms
22:08:23,923 DEBUG rusDispatcherServlet| Servlet 'vCenterServer-servlet' configured successfully
22:08:54,266 INFO server.HttpServer| Started server: vCenterServer
22:08:54,362 INFO port.LoggingReporter|
22:08:54,362 INFO port.LoggingReporter| ------------------------------------------------------------------------
22:08:54,362 INFO port.LoggingReporter| .__ __
22:08:54,362 INFO port.LoggingReporter| ____ |__|/ |________ __ __ ______
22:08:54,362 INFO port.LoggingReporter| _/ ___\| \ __\_ __ \ | \/ ___/
22:08:54,362 INFO port.LoggingReporter| \ \___| || | | | \/ | /\___ \
22:08:54,362 INFO port.LoggingReporter| \___ >__||__| |__| |____//____ >
22:08:54,362 INFO port.LoggingReporter| \/ \/
22:08:54,362 INFO port.LoggingReporter|
22:08:54,363 INFO port.LoggingReporter| C I T R U S T E S T S 2.7.8
22:08:54,363 INFO port.LoggingReporter|
22:08:54,363 INFO port.LoggingReporter| ------------------------------------------------------------------------
22:08:54,363 DEBUG port.LoggingReporter| BEFORE TEST SUITE
22:08:54,363 INFO port.LoggingReporter|
22:08:54,363 INFO port.LoggingReporter|
22:08:54,363 INFO port.LoggingReporter| BEFORE TEST SUITE: SUCCESS
22:08:54,363 INFO port.LoggingReporter| ------------------------------------------------------------------------
22:08:54,363 INFO port.LoggingReporter|
22:08:54,370 DEBUG t.TestContextFactory| Created new test context - using global variables: '{}'
22:08:54,370 INFO port.LoggingReporter|
22:08:54,370 INFO port.LoggingReporter| ------------------------------------------------------------------------
22:08:54,370 DEBUG port.LoggingReporter| STARTING TEST SampleJavaDslTest <com.grge.citrus>
22:08:54,370 INFO port.LoggingReporter|
22:08:54,370 DEBUG citrus.TestCase| Initializing test case
22:08:54,372 DEBUG context.TestContext| Setting variable: citrus.test.name with value: 'SampleJavaDslTest'
22:08:54,372 DEBUG context.TestContext| Setting variable: citrus.test.package with value: 'com.grge.citrus'
22:08:54,372 DEBUG citrus.TestCase| Test variables:
22:08:54,372 DEBUG citrus.TestCase| citrus.test.name = SampleJavaDslTest
22:08:54,372 DEBUG citrus.TestCase| citrus.test.package = com.grge.citrus
22:08:54,373 INFO actions.EchoAction| Hello from Java DSL!
22:08:54,493 INFO port.LoggingReporter|
22:08:54,493 INFO port.LoggingReporter| TEST SUCCESS SampleJavaDslTest (com.grge.citrus)
22:08:54,493 INFO port.LoggingReporter| ------------------------------------------------------------------------
22:08:54,493 INFO port.LoggingReporter|
Exception in thread "main" java.lang.NullPointerException
at com.consol.citrus.dsl.testng.TestNGCitrusTestDesigner.getTestCase(TestNGCitrusTestDesigner.java:113)
at com.grge.citrus.App.main(App.java:25)
Effectively using the debugger I can see that when entering the try section, myTest has:
applicationContext
testDesigner
and many other attributes set to null and so the testDesigner.getTestCase() raise an Exception
Thx
Since Citrus 2.7 the framework provides a main CLI class that does exactly what you want:
https://github.com/citrusframework/citrus/blob/10d3954fd6c051d32e9cd974f685322c6454c779/modules/citrus-core/src/main/java/com/consol/citrus/main/CitrusApp.java#L38
Citrus application option usage:
-h or --help = Displays cli option usage
-d or --duration = Maximum time in milliseconds the server should be up and running - server will terminate automatically when time exceeds
-c or --config = Custom Spring configuration class
-s or --skipTests = Skip test execution
-p or --package = Test package to execute
-D or --properties = Default system properties to set
-e or --exit = Force system exit when finished
-t or --test = Test class/method to execute
-j or --jar = External test jar to load tests from
Faced spring integration java-dsl issue, I'm stuck. This is a code I have for my flow declaration:
#Bean
public IntegrationFlow orchestrationFlow() {
return IntegrationFlows.from(
Jms.messageDrivenChannelAdapter(queueConnectionFactory())
.destination(bookingQueue())
.outputChannel(bookingChannel()))
.<String, BookingRequest>transform(s -> {
Ticket t = new Gson().fromJson(s, Ticket.class);
return new BookingRequest()
.setMovieId(t.getMovie().getId())
.setRow(t.getSeat().getRow())
.setSeat(t.getSeat().getNumber())
.setScreenNumber(t.getScreenNumber()
);
})
// HTTP part goes here
.<BookingRequest, HttpEntity>transform(HttpEntity::new)
.handle(
Http.outboundChannelAdapter(bookingServerUrl)
.httpMethod(HttpMethod.POST)
.extractPayload(true)
.expectedResponseType(BookStatus.class)
)
// and here HTTP part ends
.handle(
Jms.outboundAdapter(responseDestinationTemplate())
)
.get();
}
And everything was OK until I utilized HTTP outbound channel adapter. I need to call simple RESTful interface and code above does it pretty well. But, following Jms.outboundAdapter(responseDestinationTemplate()) line leads to nothing, no action performes after successfull http call.
If I remove http flow part (surrounded by comments) - it works. Implemented so much stuff, almost understood and saw beauty and simplicity of integration ...aand this is it. Yet another place I got stuck in.
And here are log after success REST call:
2016-02-08 21:01:22.155 DEBUG 18209 --- [enerContainer-1] o.s.web.client.RestTemplate : POST request for "http://localhost:9052/api/book" resulted in 200 (OK)
2016-02-08 21:01:22.156 DEBUG 18209 --- [enerContainer-1] o.s.web.client.RestTemplate : Reading [class c.e.m.integration.domain.BookStatus] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#6b9469bd]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] i.h.o.HttpRequestExecutingMessageHandler : handler 'org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler#0' produced no reply for request Message: GenericMessage [payload=<BookingRequest(movieId=0, row=1, seat=1, screenNumber=1),{}>, headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=a1fb2a2f-5d78-3183-d409-3f60aae74a20, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877352}]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'inboundFlow.channel#2', message: GenericMessage [payload=<BookingRequest(movieId=0, row=1, seat=1, screenNumber=1),{}>, headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=a1fb2a2f-5d78-3183-d409-3f60aae74a20, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877352}]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'inboundFlow.channel#1', message: GenericMessage [payload=BookingRequest(movieId=0, row=1, seat=1, screenNumber=1), headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=859af23d-214f-4400-e9cb-7d40308755cd, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877350}]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'inboundFlow.channel#0', message: GenericMessage [payload={"screenNumber":1,"seat":{"row":1,"number":1},"movie":{"id":0,"name":"The Matrix"}}, headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=636638ed-aec2-082e-6181-0484999fd807, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877331}]
No errors, no warnings at all.
Spring Integration provides two MessageHandler types: one-way - just handle message and stop. And another one is like: handle request message and produce reply to the output channel.
The first one is called like outboundChannelAdapter and with your HTTP case you just only send a POST request and don't worry about the reply.
Since the message flow is stopped on the outboundChannelAdapter no any further action is possible in the integration chain. Like in your case the next Jms.outboundAdapter won't be reached.
If you really expect the reply from your REST service you should use Http.outboundGateway instead. And your BookStatus will be sent to the JMS as you'd like by your last .handle() in the flow.
I'm using QuickFIXJ 1.5 version. I set logging level to INFO in my logj.properties file like that:
log4j.logger.quickfixj.msg.incoming=INFO
log4j.logger.quickfixj.msg.outgoing=INFO
log4j.logger.quickfixj.event=INFO
But in the application logs I see DEBUG logs of QuickFIXJ.
27-11-2014 10:20:34.172 8372 [SocketConnectorIoProcessor-0.0] DEBUG (FIXMessageDecoder.java:157) detected header: pos=0,lim=1695,rem=1695,offset=0,state=1
27-11-2014 10:20:34.172 8372 [SocketConnectorIoProcessor-0.0] DEBUG (FIXMessageDecoder.java:176) body length = 1671: pos=0,lim=1695,rem=1695,offset=17,state=3
27-11-2014 10:20:34.172 8372 [SocketConnectorIoProcessor-0.0] DEBUG (FIXMessageDecoder.java:200) message body found: pos=0,lim=1695,rem=1695,offset=1688,state=4
27-11-2014 10:20:34.172 8372 [SocketConnectorIoProcessor-0.0] DEBUG (FIXMessageDecoder.java:207) found checksum: pos=0,lim=1695,rem=1695,offset=1688,state=4
27-11-2014 10:20:34.173 8373 [SocketConnectorIoProcessor-0.0] DEBUG (FIXMessageDecoder.java:226) parsed message: pos=1695,lim=1695,rem=0,offset=1695,state=4
Why does it ignore the level setting in the log4j.properties?
Thanks