I am trying to listen to messages coming through a Tibco topic in my spring boot application. My config looks like this -
#Configuration
#EnableJms
public class TibcoConfig {
#Bean
public ConnectionFactory connectionFactory() {
TopicConnectionFactory factory = new TibjmsTopicConnectionFactory("TIBCO_BROKER_URL");
return factory;
}
#Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setClientId("client1");
factory.setPubSubDomain(true);
factory.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
return factory;
}
#Bean
public UserCredentialsConnectionFactoryAdapter authenticationConnectionFactory() {
UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter = new UserCredentialsConnectionFactoryAdapter();
userCredentialsConnectionFactoryAdapter.setTargetConnectionFactory(connectionFactory());
userCredentialsConnectionFactoryAdapter.setUsername("USERNAME");
userCredentialsConnectionFactoryAdapter.setPassword("PASSWORD");
return userCredentialsConnectionFactoryAdapter;
}
}
And my listener looks like this -
#Component
public class TibcoRequestListener {
#JmsListener(destination = "TIBCO_TOPIC_NAME", containerFactory = "jmsListenerContainerFactory")
public void receiveMessage(Message message) {
try {
TextMessage txtMsg = (TextMessage) message;
System.out.println("Received response: " + txtMsg.getText());
System.out.println("Message type: " + message.getJMSType());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Error log -
2020-07-08 18:28:37.711 WARN 3552 --- [)-10.110.74.130] o.s.boot.actuate.jms.JmsHealthIndicator : JMS health check failed
javax.jms.JMSSecurityException: authentication failed
at com.tibco.tibjms.Tibjmsx.buildException(Tibjmsx.java:575) ~[tibjms-5.1.0.jar:5.1.0]
at com.tibco.tibjms.TibjmsConnection._create(TibjmsConnection.java:1330) ~[tibjms-5.1.0.jar:5.1.0]
at com.tibco.tibjms.TibjmsConnection.<init>(TibjmsConnection.java:4115) ~[tibjms-5.1.0.jar:5.1.0]
at com.tibco.tibjms.TibjmsTopicConnection.<init>(TibjmsTopicConnection.java:36) ~[tibjms-5.1.0.jar:5.1.0]
at com.tibco.tibjms.TibjmsxCFImpl._createImpl(TibjmsxCFImpl.java:191) ~[tibjms-5.1.0.jar:5.1.0]
at com.tibco.tibjms.TibjmsxCFImpl._createConnection(TibjmsxCFImpl.java:253) ~[tibjms-5.1.0.jar:5.1.0]
at com.tibco.tibjms.TibjmsConnectionFactory.createConnection(TibjmsConnectionFactory.java:36) ~[tibjms-5.1.0.jar:5.1.0]
at org.springframework.boot.actuate.jms.JmsHealthIndicator.doHealthCheck(JmsHealthIndicator.java:52) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:82) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthIndicator.getHealth(HealthIndicator.java:37) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpoint.getHealth(HealthEndpoint.java:81) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpoint.getHealth(HealthEndpoint.java:38) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:108) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getAggregateHealth(HealthEndpointSupport.java:119) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:105) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getAggregateHealth(HealthEndpointSupport.java:119) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:105) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:83) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:70) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:75) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:65) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.boot.actuate.endpoint.invoke.reflect.ReflectiveOperationInvoker.invoke(ReflectiveOperationInvoker.java:77) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation.invoke(AbstractDiscoveredOperation.java:60) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.endpoint.jmx.EndpointMBean.invoke(EndpointMBean.java:121) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.actuate.endpoint.jmx.EndpointMBean.invoke(EndpointMBean.java:96) ~[spring-boot-actuator-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:809) ~[na:na]
at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1466) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1307) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1399) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:827) ~[na:na]
at java.base/jdk.internal.reflect.GeneratedMethodAccessor147.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359) ~[na:na]
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) ~[na:na]
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) ~[na:na]
at java.base/java.security.AccessController.doPrivileged(AccessController.java:691) ~[na:na]
at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:587) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:705) ~[na:na]
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]
2020-07-08 18:28:39.955 ERROR 3552 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Could not refresh JMS Connection for destination 'TIBCO_TOPIC_NAME' - retrying using FixedBackOff{interval=5000, currentAttempts=0, maxAttempts=unlimited}. Cause: authentication failed
2020-07-08 18:28:45.033 ERROR 3552 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Could not refresh JMS Connection for destination 'TIBCO_TOPIC_NAME' - retrying using FixedBackOff{interval=5000, currentAttempts=0, maxAttempts=unlimited}. Cause: authentication failed
...
...
...
Why is the spring boot application unable to authenticate the connection to the tibco topic even though the username and password is provided via UserCredentialsConnectionFactoryAdapter? Do I need to configure anything else?
I am able to connect to this topic and receive messages successfully using the same credentials in a different setup that doesn't use spring boot. And I need to make this work with an existing Spring boot application.
Was able to figure out the solution in case anyone else is stuck. In spring boot, TopicConnectionFactory object is not required to specify that we need to connect to a Tibco Topic (and not a Queue), which is needed in standalone application. It is automatically done when PubSubDomain property is set to true. So, use TibjmsConnectionFactory instead which has methods to set credentials. UserCredentialsConnectionFactoryAdapter is not needed at all.
I changed my config code to below and it started working!
#Configuration
#EnableJms
public class TibcoConfig {
#Bean
public ConnectionFactory connectionFactory() {
TibjmsConnectionFactory factory = new TibjmsConnectionFactory("TIBCO_BROKER_URL");
factory.setUserName("USERNAME");
factory.setUserPassword("PASSWORD");
return factory;
}
#Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setClientId("client1");
factory.setPubSubDomain(true);
factory.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
return factory;
}
}
Related
I'm using Spring Boot 3 with WebFlux. Tests run successfully, local service also works fine. Problems appear when running native image generated by gradlew bootBuildImage.
Code example:
#Configuration
public class RouteConfiguration {
#Bean
RouterFunction<ServerResponse> routerFunction(GetWordsHandler getWordsHandler) {
return RouterFunctions.route()
.GET("/api/words/", getWordsHandler)
.build();
}
}
#Component
#AllArgsConstructor
public class GetWordsHandler implements HandlerFunction<ServerResponse> {
private final WordsService wordsService;
#Override
public Mono<ServerResponse> handle(ServerRequest request) {
return wordsService.getWords()
.flatMap(wordsResponse -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(wordsResponse))
.switchIfEmpty(ServerResponse.notFound().build());
}
}
public record WordsResponse(List<String> words) {
}
Stack trace:
org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/json' not supported for bodyType=com.example.WordsResponse
at org.springframework.web.reactive.function.BodyInserters.unsupportedError(BodyInserters.java:391) ~[na:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ? Handler in.solomk.dictionary.api.handler.AddWordHandler#531fc147 [DispatcherHandler]
*__checkpoint ? org.springframework.web.filter.reactive.ServerHttpObservationFilter [DefaultWebFilterChain]
*__checkpoint ? org.springframework.web.cors.reactive.CorsWebFilter [DefaultWebFilterChain]
*__checkpoint ? HTTP POST "/api/words" [ExceptionHandlingWebHandler]
Original Stack Trace:
at org.springframework.web.reactive.function.BodyInserters.unsupportedError(BodyInserters.java:391) ~[na:na]
at org.springframework.web.reactive.function.BodyInserters.lambda$writeWithMessageWriters$11(BodyInserters.java:381) ~[na:na]
at java.base#17.0.5/java.util.Optional.orElseGet(Optional.java:364) ~[in.solomk.dictionary.DictionaryApplication:na]
at org.springframework.web.reactive.function.BodyInserters.writeWithMessageWriters(BodyInserters.java:381) ~[na:na]
at org.springframework.web.reactive.function.BodyInserters.lambda$fromPublisher$4(BodyInserters.java:185) ~[na:na]
at org.springframework.web.reactive.function.server.DefaultEntityResponseBuilder$DefaultEntityResponse.writeToInternal(DefaultEntityResponseBuilder.java:233) ~[na:na]
at org.springframework.web.reactive.function.server.DefaultServerResponseBuilder$AbstractServerResponse.writeTo(DefaultServerResponseBuilder.java:343) ~[in.solomk.dictionary.DictionaryApplication:6.0.2]
at org.springframework.web.reactive.function.server.support.ServerResponseResultHandler.handleResult(ServerResponseResultHandler.java:94) ~[in.solomk.dictionary.DictionaryApplication:6.0.2]
at org.springframework.web.reactive.DispatcherHandler.doHandleResult(DispatcherHandler.java:209) ~[in.solomk.dictionary.DictionaryApplication:6.0.2]
at org.springframework.web.reactive.DispatcherHandler.handleResult(DispatcherHandler.java:192) ~[in.solomk.dictionary.DictionaryApplication:6.0.2]
at org.springframework.web.reactive.DispatcherHandler.lambda$handleRequestWith$6(DispatcherHandler.java:184) ~[in.solomk.dictionary.DictionaryApplication:6.0.2]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:132) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) ~[na:na]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) ~[na:na]
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2508) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:171) ~[na:na]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:171) ~[na:na]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.request(MonoFlatMap.java:194) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoFlatMap$FlatMapInner.onSubscribe(MonoFlatMap.java:291) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:117) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:96) ~[na:na]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:96) ~[na:na]
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55) ~[na:na]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:165) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[na:na]
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) ~[na:na]
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.innerNext(FluxConcatMapNoPrefetch.java:258) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:863) ~[na:na]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) ~[na:na]
at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) ~[na:na]
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.innerNext(FluxConcatMapNoPrefetch.java:258) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:863) ~[na:na]
at reactor.core.publisher.FluxConcatMap$WeakScalarSubscription.request(FluxConcatMap.java:479) ~[na:na]
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.request(Operators.java:2268) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.request(FluxConcatMapNoPrefetch.java:338) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoNext$NextSubscriber.request(MonoNext.java:108) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxPeek$PeekSubscriber.request(FluxPeek.java:138) ~[na:na]
at reactor.core.publisher.FluxMap$MapSubscriber.request(FluxMap.java:164) ~[na:na]
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.request(Operators.java:2268) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.request(FluxConcatMapNoPrefetch.java:338) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoNext$NextSubscriber.request(MonoNext.java:108) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2304) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2178) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoNext$NextSubscriber.onSubscribe(MonoNext.java:70) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.onSubscribe(FluxConcatMapNoPrefetch.java:164) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165) ~[na:na]
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87) ~[na:na]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[na:na]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[na:na]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[na:na]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[na:na]
at reactor.core.publisher.Mono.subscribe(Mono.java:4444) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:263) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) ~[na:na]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[in.solomk.dictionary.DictionaryApplication:3.5.0]
at reactor.core.publisher.MonoDeferContextual.subscribe(MonoDeferContextual.java:55) ~[na:na]
at reactor.netty.http.server.HttpServer$HttpServerHandle.onStateChange(HttpServer.java:997) ~[na:na]
at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:680) ~[na:na]
at reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:477) ~[na:na]
at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:573) ~[in.solomk.dictionary.DictionaryApplication:1.1.0]
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:113) ~[in.solomk.dictionary.DictionaryApplication:1.1.0]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:220) ~[in.solomk.dictionary.DictionaryApplication:1.1.0]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:333) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:454) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[in.solomk.dictionary.DictionaryApplication:4.1.85.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) ~[na:na]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) ~[na:na]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) ~[na:na]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) ~[na:na]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[na:na]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[na:na]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[na:na]
at java.base#17.0.5/java.lang.Thread.run(Thread.java:833) ~[in.solomk.dictionary.DictionaryApplication:na]
at com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:775) ~[in.solomk.dictionary.DictionaryApplication:na]
at com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:203) ~[na:na]
Similar issue on GitHub, but there's no such classes: https://github.com/spring-projects-experimental/spring-native/issues/1721
Spring Boot version 3.0.0. Project mostly generated with Spring Initializer.
While writing my question I've found solution to this problem and decided to share with others.
Spring Native requires hints where to use reflection.
Use #RegisterReflectionForBinding(WordsResponse.class) to specify that DTO requires reflection.
Docs: https://docs.spring.io/spring-framework/docs/6.0.0/reference/html/core.html#aot-hints-register-reflection-for-binding
I've used it in the handler to put it close to the place where I create response.
#Override
#RegisterReflectionForBinding(value = WordsResponse.class)
public Mono<ServerResponse> handle(ServerRequest request) {
return wordsService.getWords()
.flatMap(wordsResponse -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(wordsResponse))
.switchIfEmpty(ServerResponse.notFound().build());
}
INFO [client-001-job-3] o.j.s.s.impl.DataLoaderService - Using registration URL of http://localhost:8080/sync/server/registration?nodeGroupId=client&externalId=001&syncURL=http%3A%2F%2Flocalhost%3A8081%2Fsync%2Fclient-001&schemaVersion=%3F&databaseType=H2&databaseVersion=1.4&symmetricVersion=3.11.9&deploymentType=client&hostName=XXXXXXX&ipAddress=XX3
ERROR [client-001-job-3] o.j.s.s.impl.RegistrationService - Unexpected error during registration: org.jumpmind.symmetric.transport.AuthenticationException
org.jumpmind.symmetric.transport.AuthenticationException: null
at org.jumpmind.symmetric.transport.http.HttpIncomingTransport.openStream(HttpIncomingTransport.java:139)
at org.jumpmind.symmetric.transport.http.HttpIncomingTransport.openReader(HttpIncomingTransport.java:156)
at org.jumpmind.symmetric.service.impl.DataLoaderService.loadDataFromTransport(DataLoaderService.java:592)
at org.jumpmind.symmetric.service.impl.DataLoaderService.loadDataFromPull(DataLoaderService.java:302)
at org.jumpmind.symmetric.service.impl.DataLoaderService.loadDataFromPull(DataLoaderService.java:258)
at org.jumpmind.symmetric.service.impl.RegistrationService.attemptToRegisterWithServer(RegistrationService.java:505)
at org.jumpmind.symmetric.service.impl.RegistrationService.registerWithServer(RegistrationService.java:481)
at org.jumpmind.symmetric.service.impl.PullService.pullData(PullService.java:89)
at org.jumpmind.symmetric.job.PullJob.doJob(PullJob.java:48)
at org.jumpmind.symmetric.job.AbstractJob.invoke(AbstractJob.java:227)
at org.jumpmind.symmetric.job.AbstractJob.run(AbstractJob.java:298)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:835)
I do not know why this symetricDS error occures.
I needed to register the clients /sync URL as well.
#Bean
public ServletRegistrationBean<SymmetricServlet> symServlet() {
ServletRegistrationBean<SymmetricServlet> bean = new ServletRegistrationBean<>(new SymmetricServlet(), "/sync/*");
bean.setLoadOnStartup(1);
return bean;
}
I am trying to trigger a spring batch job from a rest controller, and I need to pass parameters to the Step. I used a SystemCommandTasklet and, as suggested here I added the Tasklet as a StepListener, but I keep getting a NPE.
I have created a sample project here: if you run the test you will see this on the output:
java.lang.NullPointerException: null
at org.springframework.batch.core.step.tasklet.SystemCommandTasklet.execute(SystemCommandTasklet.java:133) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136) ~[spring-aop-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at com.sun.proxy.$Proxy87.execute(Unknown Source) ~[na:na]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:410) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:319) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:147) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
The method beforeStep in the Tasklet is never invoked, and that leads to the NPE.
This is my batch configuration:
#Configuration
#EnableBatchProcessing
public class BatchConfiguration extends DefaultBatchConfigurer {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
public BatchConfiguration(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
}
#Override
public JobLauncher getJobLauncher() {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(getJobRepository());
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
return jobLauncher;
}
#Bean
public Job myJob(Step myStep) {
return jobBuilderFactory.get("myJob")
.incrementer(new RunIdIncrementer())
.start(myStep)
.build();
}
#Bean
public Step myStep(Tasklet myServiceTasklet) {
return this.stepBuilderFactory.get("myStep")
.listener(myServiceTasklet)
.tasklet(myServiceTasklet)
.build();
}
#Bean
#StepScope
public Tasklet myServiceTasklet(
#Value("#{jobParameters['my_param']}") String param
) {
SystemCommandTasklet tasklet = new SystemCommandTasklet();
System.out.println(param);
tasklet.setCommand("sleep 10");
tasklet.setTimeout(20000);
return tasklet;
}
}
I tried dozens of different ways to do this, but I still can't figure out why the beforeStep method in the Tasklet is not invoked and the field execution remains null
The return type of your tasklet bean definition method should be SystemCommandTasklet:
#Bean
#StepScope
public SystemCommandTasklet myServiceTasklet(
#Value("#{jobParameters['my_param']}") String param
) {
SystemCommandTasklet tasklet = new SystemCommandTasklet();
System.out.println(param);
tasklet.setCommand("sleep 10");
tasklet.setTimeout(20000);
return tasklet;
}
Currently, it returns Tasklet and hence it is not proxied by Spring Batch as a StepExecutionListener (that's why it is not registered as a listener and the beforeStep method is not invoked).
You need to be as specific as possible for the return type of bean definition methods so that Spring Batch can correctly proxy your beans and register them with the correct type. More details here: https://stackoverflow.com/a/21941127/5019386.
NB: I downloaded your code and noticed that you do not disable jobs at startup for production code as you do in test code. You need to add the same application.properties in src/main/resources as well.
I am using mockito to test a controller. That controller uses a repository that connects to database. I want to mock userRepository and inject it in usercontroller, but when I run the test a NullPointerException is thrown at when(userRepository.addUser(anyString(), anyString())).thenReturn(true); in the test. Also when I removed this line to see whether mockMvc also gives this error and indeed it did just that.
Thus I think the problem causer is the MockitoAnnotations.initMocks(this); that it somehow doesn't enable the annotations.
I did some research about why this is happening on Google but none of the solutions solved this problem and I don't know why this is not working.
My Controller that I want to test:
#RestController
public class UserController {
#Autowired
private transient userRepository userRepository;
#PostMapping("/user/add")
public ResponseEntity<?> addUser(#RequestBody User user) {
String firstname = user.getUsername();
String lastname = user.getLastName();
boolean added = userRepository.addUser(firstname , lastname );
if(added){
return new ResponseEntity<>(true, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.CONFLICT);
}
My test so far:
#RunWith(SpringRunner.class)
class UserControllerTest {
private MockMvc mockMvc;
#MockBean
private UserRepository userRepository;
#InjectMocks
private UserController userController;
#BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders
.standaloneSetup(userController)
.build();
}
#Test
void testAddUserToDb() throws Exception {
User user = new User();
User.setFirstName("first");
User.setLastName("last");
Gson gson = new Gson();
String request = gson.toJson(user);
//HERE I GET NULLPOINTEREXCEPTION
when(userRepository.addUser(anyString(), anyString())).thenReturn(true);
mockMvc.perform(post("user/add")
.contentType(MediaType.APPLICATION_JSON).content(request))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8));
verify(userRepository, times(1)).addUser(anyString(), anyString());
verifyNoMoreInteractions(userRepository);
}
My user repository:
#Repository
public class UserRepository {
#Autowired
private transient JdbcTemplate jdbcTemplate;
public boolean addUser(String firstName, String lastName){
boolean added = false;
String ADD_USER = "INSERT INTO Users(firstName, lastname) VALUES(?, ?)";
//execute sql query and retrieve result set
int rowsHit = jdbcTemplate.update(ADD_USER, firstName, lastName);
if (rowsHit == 1) {
added = true;
}
return added;
}
ERROR MESSAGE:
java.lang.NullPointerException
at server.controller.UserControllerTest.testAddUserToDb(UserControllerTest.java:21)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:436)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170)
at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:112)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:102)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:82)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:78)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy5.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.base/java.lang.Thread.run(Thread.java:835)
Edit your test class to the code below and it should not throw any NullPointerException anymore (though you have some other compile-time errors in your code, like in the controller mixing firstname with username).
#SpringBootTest
#AutoConfigureMockMvc
#RunWith(SpringRunner.class)
public class UserControllerTest {
#Autowired
private MockMvc mockMvc;
#Mock
private UserRepository userRepository;
#Test
public void testAddUserToDb() throws Exception {
User user = new User();
user.setFirstName("first");
user.setLastName("last");
Gson gson = new Gson();
String request = gson.toJson(user);
//HERE I GET NULLPOINTEREXCEPTION
when(userRepository.addUser(anyString(), anyString())).thenReturn(true);
mockMvc.perform(post("user/add")
.contentType(MediaType.APPLICATION_JSON).content(request))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8));
verify(userRepository, times(1)).addUser(anyString(), anyString());
verifyNoMoreInteractions(userRepository);
}
}
In your gradle file you are mixing Spring (Boot) versions and some other, transient dependencies of Spring. Could you also update your Gradle file to this:
plugins {
id 'org.springframework.boot' version '2.2.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
sourceCompatibility = 12
repositories {
mavenCentral()
jcenter()
}
test {
useJUnitPlatform()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
components {
withModule('org.springframework:spring-beans') {
allVariants {
withDependencyConstraints {
it.findAll { it.name == 'snakeyaml' }.each { it.version { strictly '1.19' } }
}
}
}
}
}
bootJar {
mainClassName = 'server.Application'
}
If you'll get Exceptions complaining about a datasource, then remove implementation 'org.springframework.boot:spring-boot-starter-jdbc' from the Gradle configuration (or import a datasource dependency and configure it in Gradle, if you are using a database).
I watched video from Springone Platform and John Blum as speaker and interested try myself in Geode/Gemfire setup but with setup as described in Spring Data for Apache Geode Reference Guide
So i make spring boot geode client, locator and cache server using Eclipse, and i have problems when :
Start spring locator, start cache server, and start client with restcontroller so I can post my POJO TitleContent and get my list of TitleContent. Client give me exception Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://localhost:7070/gemfire/v1/regions": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
Complete log :
2019-10-29 09:54:12.461 ERROR 58556 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.context.ApplicationContextException: Failed to start bean 'gemfireClusterSchemaObjectInitializer'; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://localhost:7070/gemfire/v1/regions": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:185) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:894) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:162) ~[spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at network.powerhouse.commercehost.CommerceHostGeodeApplication.main(CommerceHostGeodeApplication.java:51) [classes/:na]
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://localhost:7070/gemfire/v1/regions": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:751) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:644) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.data.gemfire.config.admin.remote.RestHttpGemfireAdminTemplate.createRegion(RestHttpGemfireAdminTemplate.java:267) ~[spring-data-geode-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.data.gemfire.config.schema.definitions.RegionDefinition.create(RegionDefinition.java:125) ~[spring-data-geode-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.data.gemfire.config.annotation.ClusterConfigurationConfiguration$ClusterSchemaObjectInitializer.lambda$null$0(ClusterConfigurationConfiguration.java:403) ~[spring-data-geode-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at java.base/java.util.Optional.ifPresent(Optional.java:172) ~[na:na]
at org.springframework.data.gemfire.config.annotation.ClusterConfigurationConfiguration$ClusterSchemaObjectInitializer.lambda$start$1(ClusterConfigurationConfiguration.java:402) ~[spring-data-geode-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357) ~[na:na]
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) ~[na:na]
at org.springframework.data.gemfire.config.annotation.ClusterConfigurationConfiguration$ClusterSchemaObjectInitializer.start(ClusterConfigurationConfiguration.java:402) ~[spring-data-geode-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
... 14 common frames omitted
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:400) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:243) ~[na:na]
at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:225) ~[na:na]
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:402) ~[na:na]
at java.base/java.net.Socket.connect(Socket.java:591) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:657) ~[na:na]
at java.base/sun.security.ssl.BaseSSLSocketImpl.connect(BaseSSLSocketImpl.java:174) ~[na:na]
at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:182) ~[na:na]
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:474) ~[na:na]
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:569) ~[na:na]
at java.base/sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:265) ~[na:na]
at java.base/sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:372) ~[na:na]
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:191) ~[na:na]
at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1181) ~[na:na]
at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1075) ~[na:na]
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:177) ~[na:na]
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:163) ~[na:na]
at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:742) ~[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
... 31 common frames omitted
I remark #EnableClusterConfiguration(useHttp=true) and start Client again and now able to run. Now I give it a try with a POJO post to my restcontroller and get this exception :
2019-10-29 09:43:08.193 ERROR 57276 --- [io-15050-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataAccessResourceFailureException: remote server on 192.168.100.8(SpringBasedCacheClientApplication:57276:loner):64494:51246215:SpringBasedCacheClientApplication: : While performing a remote put; nested exception is org.apache.geode.cache.client.ServerOperationException: remote server on 192.168.100.8(SpringBasedCacheClientApplication:57276:loner):64494:51246215:SpringBasedCacheClientApplication: : While performing a remote put] with root cause
org.apache.geode.cache.RegionDestroyedException: Server connection from [identity(192.168.100.8(SpringBasedCacheClientApplication:57276:loner):64494:51246215:SpringBasedCacheClientApplication,connection=1; port=64498]: Region named /TitleContent was not found during put request
at org.apache.geode.internal.cache.tier.sockets.BaseCommand.writeRegionDestroyedEx(BaseCommand.java:624) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.command.Put65.cmdExecute(Put65.java:185) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.BaseCommand.execute(BaseCommand.java:183) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.ServerConnection.doNormalMessage(ServerConnection.java:851) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.OriginalServerConnection.doOneMessage(OriginalServerConnection.java:75) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.ServerConnection.run(ServerConnection.java:1227) ~[geode-core-1.9.1.jar:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at org.apache.geode.internal.cache.tier.sockets.AcceptorImpl.lambda$initializeServerConnectionThreadPool$3(AcceptorImpl.java:616) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.logging.LoggingThreadFactory.lambda$newThread$0(LoggingThreadFactory.java:121) ~[geode-core-1.9.1.jar:na]
at java.base/java.lang.Thread.run(Thread.java:844) [na:na]
This time I un-remark //#EnableClusterConfiguration(useHttp=true) but I remove useHttp and just use #EnableClusterConfiguration, (I suspected error because of this). I stop Spring Client and start it again. Now it fails, and says : org.apache.geode.cache.RegionExistsException: /TitleContent.
The complete log :
Application run failed
org.springframework.context.ApplicationContextException: Failed to start bean 'gemfireClusterSchemaObjectInitializer'; nested exception is org.apache.geode.cache.execute.FunctionException: org.apache.geode.cache.RegionExistsException: /TitleContent
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:185) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:894) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:162) ~[spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at network.powerhouse.commercehost.CommerceHostGeodeApplication.main(CommerceHostGeodeApplication.java:51) [classes/:na]
Caused by: org.apache.geode.cache.execute.FunctionException: org.apache.geode.cache.RegionExistsException: /TitleContent
at org.apache.geode.internal.cache.tier.sockets.command.ExecuteFunction66.cmdExecute(ExecuteFunction66.java:262) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.command.ExecuteFunction70.cmdExecute(ExecuteFunction70.java:66) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.BaseCommand.execute(BaseCommand.java:183) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.ServerConnection.doNormalMessage(ServerConnection.java:851) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.OriginalServerConnection.doOneMessage(OriginalServerConnection.java:75) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.ServerConnection.run(ServerConnection.java:1227) ~[geode-core-1.9.1.jar:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at org.apache.geode.internal.cache.tier.sockets.AcceptorImpl.lambda$initializeServerConnectionThreadPool$3(AcceptorImpl.java:616) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.logging.LoggingThreadFactory.lambda$newThread$0(LoggingThreadFactory.java:121) ~[geode-core-1.9.1.jar:na]
at java.base/java.lang.Thread.run(Thread.java:844) ~[na:na]
Caused by: org.apache.geode.cache.RegionExistsException: /TitleContent
at org.apache.geode.internal.cache.GemFireCacheImpl.createVMRegion(GemFireCacheImpl.java:2983) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.GemFireCacheImpl.basicCreateRegion(GemFireCacheImpl.java:2938) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.GemFireCacheImpl.createRegion(GemFireCacheImpl.java:2925) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.cache.RegionFactory.create(RegionFactory.java:755) ~[geode-core-1.9.1.jar:na]
at org.springframework.data.gemfire.config.admin.functions.CreateRegionFunction.createRegion(CreateRegionFunction.java:51) ~[spring-data-geode-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:279) ~[spring-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.data.gemfire.function.PojoFunctionWrapper.invokeTargetMethod(PojoFunctionWrapper.java:176) ~[spring-data-geode-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.data.gemfire.function.PojoFunctionWrapper.execute(PojoFunctionWrapper.java:155) ~[spring-data-geode-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.apache.geode.internal.cache.tier.sockets.command.ExecuteFunction66.executeFunctionLocally(ExecuteFunction66.java:320) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.command.ExecuteFunction66.cmdExecute(ExecuteFunction66.java:250) ~[geode-core-1.9.1.jar:na]
... 10 common frames omitted
This time I remark again //#EnableClusterConfiguration and start Spring Client again. This time it runs and I give a try again with the same POJO. It success !
Complete log :
Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-10-29 10:04:04.477 INFO 59413 --- [io-15050-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-10-29 10:04:04.483 INFO 59413 --- [io-15050-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 6 ms
2019-10-29 10:04:04.598 INFO 59413 --- [io-15050-exec-1] o.a.geode.pdx.internal.TypeRegistry : Caching PdxType[dsid=0, typenum=12150516
name=network.powerhouse.commercehost.model.TitleContent
fields=[
id:Object:identity:0:idx0(relativeOffset)=0:idx1(vlfOffsetIndex)=-1
code:String:1:1:idx0(relativeOffset)=0:idx1(vlfOffsetIndex)=1
title:String:2:2:idx0(relativeOffset)=0:idx1(vlfOffsetIndex)=2
content:String:3:3:idx0(relativeOffset)=0:idx1(vlfOffsetIndex)=3]]
I try to get list of TitleContent with GET rest endpoint at the controller with success.
Now I shut down all of them and restart them all. And i try to get the list as in point 5 and give me exception as in the complete log :
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataAccessResourceFailureException: remote server on 192.168.100.8(SpringBasedCacheClientApplication:59853:loner):49745:69bf7c15:SpringBasedCacheClientApplication: While performing a remote query; nested exception is org.apache.geode.cache.client.ServerOperationException: remote server on 192.168.100.8(SpringBasedCacheClientApplication:59853:loner):49745:69bf7c15:SpringBasedCacheClientApplication: While performing a remote query] with root cause
org.apache.geode.cache.query.RegionNotFoundException: Region not found: /TitleContent
at org.apache.geode.cache.query.internal.DefaultQuery.checkQueryOnPR(DefaultQuery.java:464) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.cache.query.internal.DefaultQuery.execute(DefaultQuery.java:226) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.BaseCommandQuery.processQueryUsingParams(BaseCommandQuery.java:120) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.command.Query651.cmdExecute(Query651.java:135) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.BaseCommand.execute(BaseCommand.java:183) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.ServerConnection.doNormalMessage(ServerConnection.java:851) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.OriginalServerConnection.doOneMessage(OriginalServerConnection.java:75) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.cache.tier.sockets.ServerConnection.run(ServerConnection.java:1227) ~[geode-core-1.9.1.jar:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at org.apache.geode.internal.cache.tier.sockets.AcceptorImpl.lambda$initializeServerConnectionThreadPool$3(AcceptorImpl.java:616) ~[geode-core-1.9.1.jar:na]
at org.apache.geode.internal.logging.LoggingThreadFactory.lambda$newThread$0(LoggingThreadFactory.java:121) ~[geode-core-1.9.1.jar:na]
at java.base/java.lang.Thread.run(Thread.java:844) [na:na]
The Region looks like not persist to disk.
Questions :
At point 3 as exception was thrown, but definitely TitleContent region was created. But why exception is thrown?
Can somebody pinpoint what I missed, why #EnableClusterConfiguration behave strangely in my case and why Region is not persisted to disk (according to ref. manual, it should be persisted to disk by DEFAULT DiskStore at 7.12.7 ref. manual). I am sorry for such very long questions. I just couldn't make it shorter.
Thank you if somebody may be able to help, I really appreciate it.
The complete source code list:
SERVER :
#SpringBootApplication
#CacheServerApplication(locators="localhost[10334]", name="GeodeServerApplication" )
#EnableCacheServer(name="neptunus", autoStartup=true, hostnameForClients = "localhost", port = 48484)
//#EnableCachingDefinedRegions
//#EnableGemfireCaching
#EnablePdx
#EnableManager
#EnableHttpService
public class GeodeServerApplication {
public static void main(String[] args) {
SpringApplication.run(GeodeServerApplication.class, args);
}
}
LOCATOR :
#SpringBootApplication
#LocatorApplication(port = 10334)
public class GeodeLocatorApplication {
public static void main(String[] args) {
SpringApplication.run(GeodeLocatorApplication.class, args);
}
}
CLIENT :
#SpringBootApplication
#ClientCacheApplication(logLevel = "debug", locators = {#Locator(host = "localhost", port = 10334)})
#EnablePool(name="neptunusPool", servers=#Server(host="localhost", port=48484))
#EnableGemfireRepositories(basePackageClasses= {network.powerhouse.commercehost.repository.TitleContentRepository.class})
#EnableEntityDefinedRegions(basePackageClasses= {
network.powerhouse.commercehost.model.TitleContent.class
})
#ReplicateRegion
#EnableClusterDefinedRegions
#EnableCachingDefinedRegions
#EnableGemfireCaching
#EnableIndexing
//#EnableClusterConfiguration
#EnablePdx
public class CommerceHostGeodeApplication {
public static void main(String[] args) {
SpringApplication.run(CommerceHostGeodeApplication.class, args);
}
}
CLIENT CONTROLLER :
#RestController
public class TitleContentController {
#Autowired
TitleContentService service;
#PostMapping("/titlecontent")
TitleContent postTitleContent(#RequestBody TitleContent titleContent) {
return service.save(titleContent);
}
#GetMapping("titlecontent")
List<TitleContent> getTitleContentByCode(#RequestParam("code") String code){
return service.findByCode(code);
}
}
CLIENT REPOSITORY :
#Region("TitleContent")
public interface TitleContentRepository extends CrudRepository<TitleContent, Long> {
#Trace
List<TitleContent> findByCode(String code);
}
CLIENT SERVICE :
public interface TitleContentServiceInterface {
public TitleContent save(TitleContent titleContent);
public void delete(TitleContent titleContent);
public TitleContent findById(Long id);
List<TitleContent> findByCode(String code);
}
#Service
public class TitleContentService implements TitleContentServiceInterface{
#Autowired
TitleContentRepository repo;
#Override
public TitleContent save(TitleContent titleContent) {
return repo.save(titleContent);
}
#Override
public void delete(TitleContent titleContent) {
repo.delete(titleContent);
}
#Override
public TitleContent findById(Long id) {
return repo.findById(id).get();
}
#Override
public List<TitleContent> findByCode(String code) {
return repo.findByCode(code);
}
}
POJO :
#Region("TitleContent")
public class TitleContent {
#Id
private Long id;
#Indexed
private String code;
private String title;
private String content;
public TitleContent(Long id, String code, String title, String content) {
super();
this.id = id;
this.code = code;
this.title = title;
this.content = content;
}
public TitleContent() {
super();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
#Override
public String toString() {
return "TitleContent [id=" + id + ", code=" + code + ", title=" + title + ", content=" + content + "]";
}
}
DEPENDENCIES:
<dependency>
<groupId>org.springframework.geode</groupId>
<artifactId>spring-geode-starter</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>
SPRING BOOT VERSION:
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
I finally found the way around this, after reading answer from John Blum several time from SpringData Gemfire DiskStore.
Definitely I couldn't use #EnableClusterConfiguration in my case (still wondering why). According to John, we are able to create Region using gfsh. From this I get an idea to do the same at Spring Boot CacheServer. So, how if I define my POJO at CacheServer and let annotation #EnableEntityDefinedRegions do the job to create the region at CacheServer side. Again I borrow
serverRegionShortcut = RegionShortcut.PARTITION_PERSISTENT
from John but I put it at
#EnableEntityDefinedRegions
Beside that I also need to persist my PDX type (Spring and/or Geode Gemfire do not like me if I am not persisting Pdx type at CacheServer side). So, I am using the same method to persist from SpringData Gemfire DiskStore but I implement it at CacheServer side with some additional entry at application.properties to tell spring to persist Pdx type as well.
In that way, I am able to successfully create and persisting Region at CacheServer side and also persisting Pdx as well.
Here is the complete code and application.properties I made with borrowing the idea from SpringData Gemfire DiskStore.
I appreciate if anybody able to tell me whether this work around is a good way to do or is there any other way or any better idea (still wondering though why #EnableClusterConfiguration doesn't like me while anybody else has no problem with it :=(, so if there is anybody who is able to tell me where is(are) my mistake(s) I really appreciate it ).
CLIENT :
#SpringBootApplication
#ClientCacheApplication(logLevel = "debug", locators = {#Locator(host = "localhost", port = 10334)})
#EnablePool(name="neptunusPool", servers=#Server(host="localhost", port=41414))
#EnableGemfireRepositories(basePackageClasses= {TitleContentRepository.class})
#EnableEntityDefinedRegions(basePackageClasses= {TitleContent.class
})
//#ReplicateRegion
//#EnableClusterDefinedRegions
//#EnableCachingDefinedRegions
//#EnableGemfireCaching
#EnableIndexing
//#EnableClusterConfiguration
#EnablePdx
public class CommerceHostGeodeApplication {
public static void main(String[] args) {
SpringApplication.run(CommerceHostGeodeApplication.class, args);
}
}
At client side the same POJO, Repository and RestController and nothing in application.properties except for server.port definition.
CACHESERVER :
#SpringBootApplication
#CacheServerApplication(locators="localhost[10334]", name="GeodeServerApplication" )
#EnableCacheServer(name="neptunus", autoStartup=true, hostnameForClients = "localhost", port = 41414)
#EnableCachingDefinedRegions
#EnableGemfireCaching
#EnablePdx
#EnableManager
#EnableHttpService
#EnableDiskStore(name = "disk_store")
#EnableEntityDefinedRegions(basePackageClasses= {TitleContent.class
}, serverRegionShortcut = RegionShortcut.PARTITION_PERSISTENT)
public class GeodeServerApplication {
public static void main(String[] args) {
SpringApplication.run(GeodeServerApplication.class, args);
}
}
CACHESERVER application.properties :
server.port=15010
spring.data.gemfire.disk.store.name=disk_store
spring.data.gemfire.disk.store.directory.location=/Users/ars/geode/data
spring.data.gemfire.pdx.disk-store-name=disk_store
spring.data.gemfire.pdx.persistent=true
spring.data.gemfire.management.use-http=true
Upon CacheServer start, region is created and is able to persist / save to disk.