jetcd 0.5.11 giving error when calling KVClient.Get() method - spring

I have wriiten a jetcd client wrapper in a spring application. And it uses jetcd-core 0.5.11. Getting following error while fetching the config value via KVClient.
Wrapper Method
public ByteSequence Get(String key) throws EtcdException {
GetResponse response = null;
try {
CompletableFuture<GetResponse> getFuture = EtcdClient.get(ByteSequence.from(key, StandardCharsets.UTF_8));
response = getFuture.get();
if (response.getKvs().isEmpty()) {
logger.error(String.format("Empty KeyValues returned for key: %s\n", key));
return null;
}
return response.getKvs().get(0).getValue();
} catch (Exception e) {
throw new EtcdException(new EtcdError("Error in Etcd Client GET"), e.getMessage());
}
}
Error:
java.lang.NoSuchMethodError: 'void io.netty.buffer.PooledByteBufAllocator.<init>(boolean, int, int, int, int, int, int, boolean)'
at io.grpc.netty.Utils.createByteBufAllocator(Utils.java:176) ~[grpc-netty-1.42.1.jar!/:1.42.1]
at io.grpc.netty.Utils.access$000(Utils.java:75) ~[grpc-netty-1.42.1.jar!/:1.42.1]
at io.grpc.netty.Utils$ByteBufAllocatorPreferDirectHolder.<clinit>(Utils.java:97) ~[grpc-netty-1.42.1.jar!/:1.42.1]
at io.grpc.netty.Utils.getByteBufAllocator(Utils.java:144) ~[grpc-netty-1.42.1.jar!/:1.42.1]
at io.grpc.netty.NettyClientTransport.start(NettyClientTransport.java:233) ~[grpc-netty-1.42.1.jar!/:1.42.1]
at io.grpc.internal.ForwardingConnectionClientTransport.start(ForwardingConnectionClientTransport.java:34) ~[grpc-core-1.42.1.jar!/:1.42.1]
at io.grpc.internal.ForwardingConnectionClientTransport.start(ForwardingConnectionClientTransport.java:34) ~[grpc-core-1.42.1.jar!/:1.42.1]
at io.grpc.internal.InternalSubchannel.startNewTransport(InternalSubchannel.java:259) ~[grpc-core-1.42.1.jar!/:1.42.1]
at io.grpc.internal.InternalSubchannel.access$400(InternalSubchannel.java:66) ~[grpc-core-1.42.1.jar!/:1.42.1]
at io.grpc.internal.InternalSubchannel$2.run(InternalSubchannel.java:201) ~[grpc-core-1.42.1.jar!/:1.42.1]
at io.grpc.SynchronizationContext.drain(SynchronizationContext.java:95) ~[grpc-api-1.42.1.jar!/:1.42.1]
at io.grpc.SynchronizationContext.execute(SynchronizationContext.java:127) ~[grpc-api-1.42.1.jar!/:1.42.1]
at io.grpc.internal.ManagedChannelImpl$NameResolverListener.onResult(ManagedChannelImpl.java:1872) ~[grpc-core-1.42.1.jar!/:1.42.1]
at io.grpc.NameResolver$Listener2.onAddresses(NameResolver.java:210) ~[grpc-api-1.42.1.jar!/:1.42.1]
at io.etcd.jetcd.resolver.AbstractNameResolver.doResolve(AbstractNameResolver.java:127) ~[jetcd-core-0.6.0.jar!/:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
org.pickme.etcd.client.EtcdException: io.etcd.jetcd.common.exception.EtcdException: Panic! This is a bug!

Related

Azure Blob Storage Connection

I have problems with Azure Blob Storage, when i want to upload image there is an error
Caused by: java.lang.IllegalArgumentException: prefetch > 0 required but it was 0
at reactor.core.publisher.FluxConcatMap.<init>(FluxConcatMap.java:101) ~[reactor-core-3.3.12.RELEASE.jar:3.3.12.RELEASE]
at reactor.core.publisher.Flux.concatMap(Flux.java:3673) ~[reactor-core-3.3.12.RELEASE.jar:3.3.12.RELEASE]
at com.azure.storage.common.implementation.UploadUtils.uploadFullOrChunked(UploadUtils.java:52) ~[azure-storage-common-12.14.0.jar:12.14.0]
at com.azure.storage.blob.BlobAsyncClient.uploadWithResponse(BlobAsyncClient.java:600) ~[azure-storage-blob-12.14.1.jar:12.14.1]
at com.azure.storage.blob.BlobAsyncClient.uploadWithResponse(BlobAsyncClient.java:491) ~[azure-storage-blob-12.14.1.jar:12.14.1]
at com.azure.storage.blob.BlobAsyncClient.upload(BlobAsyncClient.java:381) ~[azure-storage-blob-12.14.1.jar:12.14.1]
at com.kypnt.edutest.testcentreservice.service.ImageService.upload(ImageService.java:48) ~[main/:na]
at com.kypnt.edutest.testcentreservice.controller.image.ImageController.uploadImage(ImageController.java:19) ~[main/:na]
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.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
... 80 common frames omitted
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99) ~[reactor-core-3.3.12.RELEASE.jar:3.3.12.RELEASE]
at reactor.core.publisher.Mono.block(Mono.java:1685) ~[reactor-core-3.3.12.RELEASE.jar:3.3.12.RELEASE]
... 93 common frames omitted
I googled this but can't find the reason.
My configuration:
#Configuration
public class AzureStorageBlobClientConfig {
#Value("${azure.storage.connection-string}")
private String connectionString;
#Value("${azure.storage.container-name}")
private String containerName;
#Bean
public BlobServiceAsyncClient blobServiceClient() {
return new BlobServiceClientBuilder().connectionString(connectionString).buildAsyncClient();
}
#Bean
public BlobContainerAsyncClient blobAsyncClient() {
return blobServiceClient().getBlobContainerAsyncClient(containerName);
}
}
My Service:
#Slf4j
#Service
public class ImageService {
#Autowired
private BlobContainerAsyncClient blobContainerAsyncClient;
private int blockSize = 10 * 1024;
private int numBuffers = 5;
public MyResponse<?> upload(MultipartFile file) {
if (file.isEmpty())
throw new BadRequestException("No File");
String fileName = UUID.randomUUID() + file.getOriginalFilename();
try {
BlobAsyncClient blobAsyncClient = blobContainerAsyncClient.getBlobAsyncClient(fileName);
Flux<ByteBuffer> data = Flux.just(ByteBuffer.wrap(file.getInputStream().readAllBytes()));
ParallelTransferOptions parallelTransferOptions = new ParallelTransferOptions(numBuffers, blockSize, null);
blobAsyncClient.upload(data, parallelTransferOptions, true).block();
// BlobContainerClient container = new BlobContainerClientBuilder()
// .connectionString(connectionString)
// .containerName(containerName)
// .buildClient();
//
// BlobClient blobClient = container.getBlobClient(fileName);
//
// blobClient.upload(file.getInputStream(), file.getSize(), true);
// blobClient
// .blobName(fileName)
// .buildClient()
// .upload(file.getInputStream(), file.getSize());
} catch (IOException e) {
log.warn(e.getMessage());
// throw new EdutestException(ErrorType.INTERNAL_ERROR);
}
return new OKResponse<>("Good");
}
}
Those commented codes, tutorial that I have tried but all of them returning this exception.
There I get my connection string and created container and get its name:
My gradle:
plugins {
id 'org.springframework.boot' version '2.3.7.RELEASE'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
// some code
dependencies {
implementation 'com.azure:azure-storage-blob:12.14.1'
implementation group: 'com.azure', name: 'azure-identity', version: '1.4.1'
}
// some code
Finally I found that problem was in new versions of "azure storage blob"
It is using new 'reactor-netty-core' and 'reactor-netty-http' but with old codes, or something like that, read about it here
To fix it use versions older:
implementation group: 'com.azure.spring', name: 'azure-spring-boot-starter-storage', version: '3.1.0'
You can use this version. When problem exist, I used version '3.10.0'. Didn't test other versions.

Spring integration / GCP PubSub : channel subscriber lost

Everything is mostly in the title.
I have a specific channel to send data to PubSub, using Spring integration and this information about GCP PubSub
I don't have any problem locally, or on the QA env.
But, in the prod, I have the following error :
org.springframework.messaging.MessageDeliveryException: failed to send Message to channel
'pubSubFlow.channel#1'; nested exception is java.lang.IllegalStateException: The [bean
'pubSubFlow.channel#1'; defined in: 'class path resource [fr/auchan/lark/tracking/api/v1
/pubsub/PubSubRequestIntegration.class]'; from source: 'bean method pubSubFlow'] doesn't
have subscribers to accept messages
org.springframework.integration.support.utils.IntegrationUtils.wrapInDeliveryExceptionIfNecessary(IntegrationUtils.java:167) ~[spring-integration-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:600) ~[spring-integration-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:520) ~[spring-integration-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
org.springframework.integration.channel.FluxMessageChannel.lambda$subscribeTo$2(FluxMessageChannel.java:83) ~[spring-integration-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:189) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]
reactor.core.publisher.FluxPublishOn$PublishOnSubscriber.runAsync(FluxPublishOn.java:439) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]
reactor.core.publisher.FluxPublishOn$PublishOnSubscriber.run(FluxPublishOn.java:526) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]
reactor.core.scheduler.WorkerTask.call(WorkerTask.java:84) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]
reactor.core.scheduler.WorkerTask.call(WorkerTask.java:37) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]
java.base/java.util.concurrent.FutureTask.run(Unknown Source) ~[na:na]
java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
Caused by: java.lang.IllegalStateException: The [bean 'pubSubFlow.channel#1'; defined in: 'class path resource [PubSubRequestIntegration.class]'; from source: 'bean method pubSubFlow'] doesn't have subscribers to accept messages
org.springframework.util.Assert.state(Assert.java:97) ~[spring-core-5.2.12.RELEASE.jar:5.2.12.RELEASE]
org.springframework.integration.channel.FluxMessageChannel.doSend(FluxMessageChannel.java:61) ~[spring-integration-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:570) ~[spring-integration-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
12 common frames omitted
Below is my channel declaration, and the use of ServiceActivator as written is the PubSub Guidelines (see the link above).
#Bean
public MessageChannel dataChannel() {
return MessageChannels.publishSubscribe(Executors.newCachedThreadPool()).get();
}
#Bean
public MessageChannel pubSubChannel() {
return MessageChannels.publishSubscribe(Executors.newCachedThreadPool()).get();
}
#Bean
public IntegrationFlow pubSubFlow(
MessageChannel dataChannel,
MessageChannel pubSubChannel) {
return IntegrationFlows
.from(dataChannel)
.fluxTransform(this::toPubSubFormat)
.channel(pubSubChannel)
.get();
}
#Bean
#ServiceActivator(inputChannel = "pubSubChannel")
public PubSubMessageHandler sendToPubSub(PubSubTemplate pubSubTemplate) {
PubSubMessageHandler adapter = new PubSubMessageHandler(pubSubTemplate,
pubSubIntegrationProperties.getTopic());
adapter.setPublishCallback(
new ListenableFutureCallback<>() {
#Override
public void onFailure(Throwable throwable) {
log.warn("There was the following error sending the message. " + throwable);
}
#Override
public void onSuccess(String result) {
log.debug("Message was sent via the outbound channel adapter to {} : {}", pubSubIntegrationProperties.getTopic(), result);
}
});
return adapter;
}
Did I miss something? Why is the pubSubChannel marked as having no subscribers?
Thanks for the help

How to propogate an exception from tcp outbound gateway to upstream SI components

I have been searching over the internet and have been trying different ways to make it work but I couldn't get it working.
Actually my system need to connect to multiple tcp server endpoints (which we call payers endpoint) as a tcp client application. The client components include the throttling and queuing components and they get initialized dynamically based on the payers configurations stored in DB as a separate application context. I have created a tcp outbound gateway for this purpose and which is being initialized in a dynamic context based on the ideas given in
https://github.com/spring-projects/spring-integration-samples/tree/master/advanced
What I want is to catch/get exceptions to the calling code at the time calling the payersGateway component in case of any error. But I am unable to receive the exceptions back.
My context file for tcp client connectivity is as follow:
dynamic-tcp-gateway-context file
<context:property-placeholder/>
<int-ip:tcp-connection-factory id="client"
type="client"
host="${host}"
port="${port}"
single-use="true"
so-timeout="${soTimeout}"
serializer="byteArrayLfSerializer"
deserializer="ediTcpSerializer"
/>
<bean id="ediTcpSerializer" class="com.abc.throttling.EdiTcpSerializer">
<property name="maxMessageSize" value="20480000"/>
</bean>
<bean id="byteArrayLfSerializer" class="org.springframework.integration.ip.tcp.serializer.ByteArrayLfSerializer">
<property name="maxMessageSize" value="20480000"/>
</bean>
<int:channel id="toPayerChannel">
<int:dispatcher task-executor="producerThreadExecutor"/>
</int:channel>
<task:executor id="producerThreadExecutor" pool-size="10" queue-capacity="50" rejection-policy="ABORT"/>
<int:channel id="throttlerChannel">
<int:priority-queue capacity="${queueSize:1000}"/> <!-- for example queue size, you can increase this capacity
based on your
requirement -->
</int:channel>
<int:bridge input-channel="toPayerChannel" output-channel="throttlerChannel" />
<int-ip:tcp-outbound-gateway id="outGateway"
request-channel="throttlerChannel"
connection-factory="client"
request-timeout="10000"
reply-timeout="${replyTimeout}">
<int:poller id="tcpPoller" error-channel="errorChannel" fixed-rate="1000" max-messages-per-poll="${messageRate:20}"/>
</int-ip:tcp-outbound-gateway>
<int:transformer input-channel="errorChannel"
ref="exceptionTransformer" method="createErrorResponse"/>
<bean id="exceptionTransformer" class="com.stella.healthenet.throttling.TcpGatewayExceptionTransformer"/>
<int:object-to-string-transformer input-channel="errorChannel"/>
application context for main payers connectivity is as follow:
main-payers-gateway-context file
<context:component-scan base-package="com.abc.throttling" />
class="com.abc.throttling.DynamicTcpChannelResolverTest" id="dynamicTcpChannelResolverTest"/>-->
<int:gateway id="payersGateway"
service-interface="com.abc.gateway.PayersGateway"
default-request-channel="toDynRouter"
default-request-timeout="1000000"
default-reply-timeout="${payersGateway.defaultReplyTimout}"
/>
<int:converter ref="converter"/>
<bean class="com.abc.manager.edi.core.core4.ByteArrayToStringConverter" id="converter"/>
<int:converter ref="converter2"/>
<bean class="com.abc.manager.edi.core.core2.Core2RealTimeResponseToString" id="converter2"/>
<int:converter ref="converter3"/>
<bean class="com.abc.manager.edi.core.core4.Core4RealTimeResponseToString" id="converter3"/>
<int:channel id="toDynRouter" />
<int:router resolution-required="true" input-channel="toDynRouter"
expression="#dynamicPayerChannelResolver.resolve(headers['payer'])" >
</int:router>
The code for dynamic channel resolver is as follow:
#Component("dynamicPayerChannelResolver")
public class DynamicPayerChannelResolver {
#Value("${throttling.payersChannelQueueSize}")
private String payersChannelQueueSize;
#Value("${throttling.tcpSoTimeout}")
private String tcpSoTimeout;
#Value("${tcpOutboundGateway.replyTimeout}")
private String tcpReplyTimeout;
#Autowired
private ApplicationContext applicationContext;
public static final int MAX_CACHE_SIZE = 30;
private static final org.apache.logging.log4j.Logger LOG = LogManager.getLogger();
#Autowired
PayerRepositoryService payerRepositoryService;
private final Map<UUID, MessageChannel> channels = Collections.synchronizedMap(new LinkedHashMap<UUID,
MessageChannel>(){
private static final long serialVersionUID = 1L;
#Override
protected boolean removeEldestEntry(
Entry<UUID, MessageChannel> eldest) {
//This returning true means the least recently used
//channel and its application context will be closed and removed
boolean remove = size() > MAX_CACHE_SIZE;
if(remove) {
MessageChannel channel = eldest.getValue();
ConfigurableApplicationContext ctx = contexts.get(channel);
if(ctx != null) { //shouldn't be null ideally
ctx.close();
contexts.remove(channel);
}
}
return remove;
}
});
private final Map<MessageChannel, ConfigurableApplicationContext> contexts =
new HashMap<MessageChannel, ConfigurableApplicationContext>();
/**
* Resolve a payer to a channel, where each payer gets a private
* application context and the channel is the inbound channel to that
* application context.
*
* #param payer
* #return a channel
*/
public MessageChannel resolve(UUID payer) {
MessageChannel channel = this.channels.get(payer);
if (channel == null) {
channel = createNewPayerChannel(payerRepositoryService.findPayerByPayerId(payer));
}
return channel;
}
private synchronized MessageChannel createNewPayerChannel(PayerEntity payer) {
MessageChannel channel = this.channels.get(payer.getPayerId());
if (channel == null) {
ConfigurableApplicationContext ctx;
if(TransportType.SOAP_WSDL.getValue().equals(payer.getConnTransportType())){
ctx = new ClassPathXmlApplicationContext(
new String[] { "dynamic-soap-gateway-context.xml" },
false,applicationContext);
}
else{
ctx = new ClassPathXmlApplicationContext(
new String[] { "dynamic-tcp-gateway-context.xml" },
false,applicationContext);
}
this.setEnvironmentForPayer(ctx, payer);
ctx.refresh();
channel = ctx.getBean("toPayerChannel", MessageChannel.class);
this.channels.put(payer.getPayerId(), channel);
//Will works as the same reference is presented always
this.contexts.put(channel, ctx);
}
return channel;
}
public void updatePollerConfigs() {
Iterator it = this.channels.entrySet().iterator();
while(it.hasNext()){
Map.Entry pair = (Map.Entry)it.next();
PayerEntity payer = this.payerRepositoryService.findPayerByPayerId((UUID)pair.getKey());
final String transportType = payer.getConnTransportType();
if(TransportType.SOAP_WSDL.getValue().equals(transportType)){
MessageChannel channel= this.channels.get(payer);
ConfigurableApplicationContext ctx;
ctx=this.contexts.get(channel);
PollingConsumer pc = ctx.getBean("soapPoller",PollingConsumer.class);
//TODO: this value need to be set from payer configs in db.
pc.setMaxMessagesPerPoll(10);
}
else if (TransportType.X12_SOCKET.getValue().equals(transportType)) {
MessageChannel channel= this.channels.get(payer);
ConfigurableApplicationContext ctx;
ctx=this.contexts.get(channel);
PollingConsumer pc = ctx.getBean("outGateway",PollingConsumer.class);
//TODO: this value need to be set from payer configs in db.
pc.setMaxMessagesPerPoll(10);
}
}
}
private void setEnvironmentForPayer(ConfigurableApplicationContext ctx,
PayerEntity payer) {
final String transportType = payer.getConnTransportType();
final String endPoint = payer.getConnEndPoint();
if(payer.getMessageRate()==null){
throw new NullPointerException("MessageRate value is NULL in DB. Please specify a MessageRate value in " +
"Payers DB for PayerID: " + payer.getPayerId());
}
final String messageRate = payer.getMessageRate();
StandardEnvironment env = new StandardEnvironment();
Properties props = new Properties();
// populate properties for payer
;
if(TransportType.SOAP_WSDL.getValue().equals(transportType)){
props.setProperty("endpoint", endPoint);
props.setProperty("messageRate",messageRate);
props.setProperty("queueSize",payersChannelQueueSize);
}
else if (TransportType.X12_SOCKET.getValue().equals(transportType)) {
if (!endPoint.contains(":")) {
throw new Exception(ErrorType.UNEXPECTED, "Payer X12 Socket endpoint must include a port.");
}
final String ip;
if (endPoint.contains("/")) {
ip = endPoint.substring(endPoint.lastIndexOf('/') + 1, endPoint.lastIndexOf(":"));
} else {
ip = endPoint.substring(0, endPoint.lastIndexOf(":"));
}
final String port = endPoint.substring(endPoint.lastIndexOf(':') + 1);
props.setProperty("host", ip);
props.setProperty("port", port);
props.setProperty("messageRate",messageRate);
props.setProperty("queueSize",payersChannelQueueSize);
props.setProperty("soTimeout", tcpSoTimeout);
props.setProperty("replyTimeout",tcpReplyTimeout);
}
PropertiesPropertySource pps = new PropertiesPropertySource("payerChannelProps", props);
env.getPropertySources().addLast(pps);
ctx.setEnvironment(env);
}
I want to get the exceptions generated at the downstream components to appear at the payersGateway interface send method call i.e., shown below:
String response = payersGateway.send(
MessageBuilder.withPayload(requestMessage)
.setHeader("endpointUrl", endPoint)
.setHeader("senderId", coreSenderId)
.setHeader("receiverId", payerIdCode)
.setHeader("username", username)
.setHeader("password", password)
.setHeader("payloadType", payloadType)
.setHeader("nginxUrl", nginxUrl)
.setHeader("payer", payerId)
.setHeader("transType", transType)
.setHeader("priority", 1)
.build());
where the payersGateway is simple interface pointing to Gateway component in main context file.
public interface PayersGateway {
public String send(Message<String> message);
}
Please see the stack trace of produced exception as below:
[task-scheduler-1] ERROR org.springframework.integration.ip.tcp.TcpOutboundGateway - Tcp Gateway exception
java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at java.net.Socket.<init>(Socket.java:434)
at java.net.Socket.<init>(Socket.java:211)
at javax.net.DefaultSocketFactory.createSocket(SocketFactory.java:271)
at org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory.createSocket(TcpNetClientConnectionFactory.java:76)
at org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory.buildNewConnection(TcpNetClientConnectionFactory.java:49)
at org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.obtainNewConnection(AbstractClientConnectionFactory.java:116)
at org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.obtainConnection(AbstractClientConnectionFactory.java:79)
at org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.getConnection(AbstractClientConnectionFactory.java:69)
at org.springframework.integration.ip.tcp.TcpOutboundGateway.handleRequestMessage(TcpOutboundGateway.java:130)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:109)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.endpoint.PollingConsumer.handleMessage(PollingConsumer.java:129)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:272)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.access$000(AbstractPollingEndpoint.java:58)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:190)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:186)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:353)
at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:55)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:51)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:344)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
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)
[task-scheduler-1] ERROR org.springframework.integration.handler.LoggingHandler - org.springframework.messaging.MessagingException: Failed to send or receive; nested exception is java.net.ConnectException: Connection refused (Connection refused)
at org.springframework.integration.ip.tcp.TcpOutboundGateway.handleRequestMessage(TcpOutboundGateway.java:158)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:109)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.endpoint.PollingConsumer.handleMessage(PollingConsumer.java:129)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:272)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.access$000(AbstractPollingEndpoint.java:58)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:190)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:186)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:353)
at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:55)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:51)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:344)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
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)
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at java.net.Socket.<init>(Socket.java:434)
at java.net.Socket.<init>(Socket.java:211)
at javax.net.DefaultSocketFactory.createSocket(SocketFactory.java:271)
at org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory.createSocket(TcpNetClientConnectionFactory.java:76)
at org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory.buildNewConnection(TcpNetClientConnectionFactory.java:49)
at org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.obtainNewConnection(AbstractClientConnectionFactory.java:116)
at org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.obtainConnection(AbstractClientConnectionFactory.java:79)
at org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.getConnection(AbstractClientConnectionFactory.java:69)
at org.springframework.integration.ip.tcp.TcpOutboundGateway.handleRequestMessage(TcpOutboundGateway.java:130)
... 21 more
It should work as you need; exceptions before the throttlerChannel will be thrown directly to the caller; exceptions after that channel will be sent to the gateway by the poller's error handler.
Perhaps your gateway timeout is too short?
Turning on DEBUG logging and following the message flow should help you debug it.
EDIT
You can fix the missing failedMessage by adding a bean of this type to the Tcp outbound gateway's <int-ip:request-handler-advice-chain />...
public class FailedMessagePopulator extends AbstractRequestHandlerAdvice {
#Override
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
try {
return callback.execute();
}
catch (MessagingException e) {
if (e.getFailedMessage() == null) {
throw new MessageHandlingException(message, e.getMessage(), e);
}
else {
throw e;
}
}
catch (Exception e) {
throw new MessageHandlingException(message, e.getMessage(), e);
}
}
}
Note that you will need to add the error channel to the <gateway/> since the poller will now see the failed message and send the exception back to the gateway for error handling.

Writing java based JMS Client for WildFly10

I writing java based JMS Client for WildFly10 and I had problem
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
props.put(Context.PROVIDER_URL, WILDFLY_REMOTING_URL); // NOTICE: "http- remoting" and port "8080"
props.put(Context.SECURITY_PRINCIPAL, JMS_USERNAME);
props.put(Context.SECURITY_CREDENTIALS, JMS_PASSWORD);
//props.put("jboss.naming.client.ejb.context", true);
context = new InitialContext(props);
i run your client code and i got this error:
Got initial Context: javax.naming.InitialContext#5442a311
Exception in thread “main” org.jboss.naming.remote.protocol.NamingIOException: Failed to lookup [Root exception is java.io.IOException: java.lang.ClassNotFoundException: org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory]
at org.jboss.naming.remote.client.ClientUtil.namingException(ClientUtil.java:49)
at org.jboss.naming.remote.protocol.v1.Protocol$1.execute(Protocol.java:104)
at org.jboss.naming.remote.protocol.v1.RemoteNamingStoreV1.lookup(RemoteNamingStoreV1.java:95)
at org.jboss.naming.remote.client.HaRemoteNamingStore$1.operation(HaRemoteNamingStore.java:276)
at org.jboss.naming.remote.client.HaRemoteNamingStore.namingOperation(HaRemoteNamingStore.java:137)
at org.jboss.naming.remote.client.HaRemoteNamingStore.lookup(HaRemoteNamingStore.java:272)
at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:87)
at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:129)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at com.almasprocess.model.bl.WildFlyJmsQueueSender.init(WildFlyJmsQueueSender.java:49)
at com.almasprocess.model.bl.WildFlyJmsQueueSender.main(WildFlyJmsQueueSender.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.io.IOException: java.lang.ClassNotFoundException: org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory
at org.jboss.naming.remote.protocol.v1.Protocol$1$3.read(Protocol.java:159)
at org.jboss.naming.remote.protocol.v1.Protocol$1$3.read(Protocol.java:149)
at org.jboss.naming.remote.protocol.v1.BaseProtocolCommand.readResult(BaseProtocolCommand.java:59)
at org.jboss.naming.remote.protocol.v1.Protocol$1.handleClientMessage(Protocol.java:149)
at org.jboss.naming.remote.protocol.v1.RemoteNamingStoreV1$MessageReceiver$1.run(RemoteNamingStoreV1.java:232)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:340)
at org.jboss.marshalling.AbstractClassResolver.loadClass(AbstractClassResolver.java:131)
at org.jboss.marshalling.AbstractClassResolver.resolveClass(AbstractClassResolver.java:112)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadClassDescriptor(RiverUnmarshaller.java:1002)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1256)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:276)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:209)
at org.jboss.marshalling.AbstractObjectInput.readObject(AbstractObjectInput.java:41)
at org.jboss.naming.remote.protocol.v1.Protocol$1$3.read(Protocol.java:156)
… 7 more
Process finished with exit code 1
And I changed code like this and add activemq lib in my project:
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
props.put(Context.PROVIDER_URL, WILDFLY_REMOTING_URL); // NOTICE: "http-remoting" and port "8080"
props.put(Context.SECURITY_PRINCIPAL, JMS_USERNAME);
props.put(Context.SECURITY_CREDENTIALS, JMS_PASSWORD);
and i got this error :
Got initial Context: javax.naming.InitialContext#6842775d
Exception in thread "main" javax.naming.NameNotFoundException: jms/RemoteConnectionFactory
at org.apache.activemq.jndi.ReadOnlyContext.lookup(ReadOnlyContext.java:225)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at com.almasprocess.model.bl.WildFlyJmsQueueSender.init(WildFlyJmsQueueSender.java:49)
at com.almasprocess.model.bl.WildFlyJmsQueueSender.main(WildFlyJmsQueueSender.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
and standalone-full.xml config file like this :
<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
<server name="default">
<security-setting name="#">
<role name="guest" send="true" consume="true" create-non-durable-queue="true" delete-non-durable-queue="true"/>
</security-setting>
<address-setting name="#" dead-letter-address="jms.queue.DLQ" expiry-address="jms.queue.ExpiryQueue" max-size-bytes="10485760" page-size-bytes="2097152" message-counter-history-day-limit="10"/>
<http-connector name="http-connector" socket-binding="http" endpoint="http-acceptor"/>
<http-connector name="http-connector-throughput" socket-binding="http" endpoint="http-acceptor-throughput">
<param name="batch-delay" value="50"/>
</http-connector>
<in-vm-connector name="in-vm" server-id="0"/>
<http-acceptor name="http-acceptor" http-listener="default"/>
<http-acceptor name="http-acceptor-throughput" http-listener="default">
<param name="batch-delay" value="50"/>
<param name="direct-deliver" value="false"/>
</http-acceptor>
<in-vm-acceptor name="in-vm" server-id="0"/>
<jms-queue name="ExpiryQueue" entries="java:/jms/queue/ExpiryQueue"/>
<jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
<jms-queue name="clickQueue" entries="java:/jms/queue/clickQueue java:/jboss/exported/jms/queue/clickQueue"/>
<jms-queue name="emailQueue" entries="java:/jms/queue/EmailQueue java:/jboss/exported/jms/queue/EmailQueue"/>
<jms-queue name="emailSendQueue" entries="java:/jboss/exported/jms/queue/EmailSendQueue"/>
<connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/>
<connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="http-connector"/>
<pooled-connection-factory name="activemq-ra" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm" transaction="xa"/>
</server>
</subsystem>
can you help me about error???
thanks.
Working example:
public class JMSClient {
private static final String INITIAL_CONTEXT_FACTORY = "org.jboss.naming.remote.client.InitialContextFactory";
private static final String PROVIDER_URL = "http-remoting://127.0.0.1:8080";
private static final String CONNECTION_FACTORY = "jms/RemoteConnectionFactory";
private static final String DESTINATION = "topic/irisWebBroadcaster";
private static final String USERNAME = "jmsuser";
private static final String PASSWORD = "qqq";
public static void main(String[] args) {
Context namingContext = null;
JMSContext context = null;
try {
final Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
env.put(Context.PROVIDER_URL, PROVIDER_URL);
env.put(Context.SECURITY_PRINCIPAL, USERNAME);
env.put(Context.SECURITY_CREDENTIALS, PASSWORD);
namingContext = new InitialContext(env);
ConnectionFactory connectionFactory = (ConnectionFactory) namingContext.lookup(CONNECTION_FACTORY);
Destination destination = (Destination) namingContext.lookup(DESTINATION);
context = connectionFactory.createContext(USERNAME, PASSWORD);
JMSProducer producer = context.createProducer();
producer.send(destination, "TEST");
} catch (Exception e) {
// print error messge
} finally {
if (namingContext != null) {
try {
namingContext.close();
} catch (NamingException e) {
// print error messge
}
}
if (context != null) {
context.close();
}
}
}
}
Corresponding classpath (maybe excessive):
[WILDFLY10_DIR]/modules/system/layers/base/javax/annotation/api/main/jboss-annotations-api_1.2_spec-1.0.0.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/javax/servlet/api/main/jboss-servlet-api_3.1_spec-1.0.0.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/javax/ejb/api/main/jboss-ejb-api_3.2_spec-1.0.0.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/javax/enterprise/api/main/cdi-api-1.2.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/jboss/log4j/logmanager/main/log4j-jboss-logmanager-1.1.2.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/javax/inject/api/main/javax.inject-1.jar
[WILDFLY10_DIR]/modules/system/layers/base/javax/ws/rs/api/main/jboss-jaxrs-api_2.0_spec-1.0.0.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/javax/jms/api/main/jboss-jms-api_2.0_spec-1.0.0.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/codehaus/jackson/jackson-core-asl/main/jackson-core-asl-1.9.13.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/codehaus/jackson/jackson-mapper-asl/main/jackson-mapper-asl-1.9.13.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/jboss/logging/main/jboss-logging-3.3.0.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/jboss/logmanager/main/jboss-logmanager-2.0.3.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/jboss/remote-naming/main/jboss-remote-naming-2.0.4.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/jboss/xnio/main/xnio-api-3.3.4.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/jboss/xnio/nio/main/xnio-nio-3.3.4.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/jboss/remoting/main/jboss-remoting-4.0.18.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/jboss/marshalling/main/jboss-marshalling-1.4.10.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/jboss/marshalling/river/main/jboss-marshalling-river-1.4.10.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/apache/activemq/artemis/main/artemis-jms-client-1.1.0.wildfly-011.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/apache/activemq/artemis/main/artemis-core-client-1.1.0.wildfly-011.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/apache/activemq/artemis/main/artemis-commons-1.1.0.wildfly-011.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/apache/activemq/artemis/main/artemis-selector-1.1.0.wildfly-011.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/apache/commons/beanutils/main/commons-beanutils-1.9.2.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/apache/commons/collections/main/commons-collections-3.2.2.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/slf4j/jcl-over-slf4j/main/jcl-over-slf4j-1.7.7.jbossorg-1.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/slf4j/main/slf4j-api-1.7.7.jbossorg-1.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/slf4j/impl/main/slf4j-jboss-logmanager-1.0.3.GA.jar
[WILDFLY10_DIR]/modules/system/layers/base/org/jboss/ejb-client/main/jboss-ejb-client-2.1.4.Final.jar
[WILDFLY10_DIR]/modules/system/layers/base/io/netty/main/netty-all-4.0.32.Final.jar
You can add something like this if you have problems with logging:
InternalLoggerFactory.setDefaultFactory(new Log4JLoggerFactory());
PropertyConfigurator.configure("conf/log4j.properties");
I see that Answer given by Rudik is not yet accepted , hence posting my take on this problem.
Test case
#Test
public void sendMessagesToWildfly10() throws IOException, NamingException {
String Message = "Hello, World!";
String connectionFactoryJNDIName = "jms/RemoteConnectionFactory";
String queueName = "jms/queue/TestQueue";
Context namingContext = null;
JMSContext context = null;
try {
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY,"org.jboss.naming.remote.client.InitialContextFactory");
env.put(Context.PROVIDER_URL, "http-remoting://localhost:8470");
// Below May Not be needed if you have turned off the security for Messaging
env.put(Context.SECURITY_PRINCIPAL, "guest");
env.put(Context.SECURITY_CREDENTIALS, "guest");
namingContext = new InitialContext(env);
ConnectionFactory connectionFactory = (ConnectionFactory) namingContext.lookup(connectionFactoryJNDIName);
Destination destination = (Destination) namingContext.lookup(queueName);
context = connectionFactory.createContext("userName", "password");
JMSProducer producer = context.createProducer();
for (int i = 0; i < 10; i++) {
producer.send(destination, Message+" - "+i);
}
JMSConsumer consumer = context.createConsumer(destination);
for (int i = 0; i < 10; i++) {
String text = consumer.receiveBody(String.class, 5000);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (namingContext != null) {
namingContext.close();
}
if (context != null) {
context.close();
}
}
}
You will require below mentioned Jars/dependencies added to your classpath. Most of them you can find in Wildfly/modules
If a JMS client is running within a WildFly application then the org.apache.activemq.artemis module must be added as a dependency on your deployment to avoid the java.lang.ClassNotFoundException: org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory, e.g. as answered here.
Otherwise ( standalone java application) - the jboss-client.jar needs to be included into class-path.
Note: take the jboss-client.jar based on your target WildFly version because it differs between WildFLy 8 and 10.

Custom Liquibase Change error when integrating with Spring: Unknown Liquibase extension. Are you missing a jar from your classpath?

As part of the database upgrade for an existing application, a custom Liquibase change which extends AbstractChange has been created:
#DatabaseChange(name = "springBeanChange", description = "Runs a spring bean custom change", priority = ChangeMetaData.PRIORITY_DEFAULT)
public class SpringBeanChange extends AbstractChange {
private String beanName;
private String changeClass;
#DatabaseChangeProperty(description = "Spring bean name (optional)")
public String getBeanName() {
return this.beanName;
}
public void setBeanName(final String beanName) {
this.beanName = beanName;
}
#DatabaseChangeProperty(description = "Spring bean class")
public String getChangeClass() {
return this.changeClass;
}
public void setChangeClass(final String changeClass) {
this.changeClass = changeClass;
}
private CustomTaskChange bean;
#Override
public boolean generateStatementsVolatile(final Database database) {
return true;
}
#Override
public String getConfirmationMessage() {
return findBean().getConfirmationMessage();
}
#Override
public SqlStatement[] generateStatements(final Database database) {
try {
findBean().execute(database);
} catch (CustomChangeException e) {
throw new UnexpectedLiquibaseException(e);
}
return new SqlStatement[0];
}
#SuppressWarnings("unchecked")
private CustomTaskChange findBean() {
Class<CustomTaskChange> requiredType = CustomTaskChange.class;
if (this.changeClass != null) {
try {
Class<?> requestedType = Class.forName(this.changeClass);
if (CustomTaskChange.class.isAssignableFrom(requestedType)) {
requiredType = (Class<CustomTaskChange>) requestedType;
} else {
throw new UnexpectedLiquibaseException(
"Specified changeClass " + this.changeClass
+ " was not an instance of "
+ CustomTaskChange.class);
}
} catch (ClassNotFoundException e) {
throw new UnexpectedLiquibaseException(
"Could not create change class", e);
}
}
if (this.bean == null) {
if (getBeanName() == null) {
this.bean = SpringContextHolder.getInstance().getContext()
.getBean(requiredType);
} else {
this.bean = SpringContextHolder.getInstance().getContext()
.getBean(getBeanName(), requiredType);
}
}
return this.bean;
}
#Override
public ValidationErrors validate(final Database database) {
try {
return findBean().validate(database);
} catch (NullPointerException p_exception) {
return new ValidationErrors()
.addError("Exception thrown calling validate():"
+ p_exception.getMessage());
} catch (UnexpectedLiquibaseException p_exception) {
return new ValidationErrors()
.addError("Exception thrown calling validate():"
+ p_exception.getMessage());
} catch (NoSuchBeanDefinitionException p_exception) {
return new ValidationErrors()
.addError("Exception thrown calling validate():"
+ p_exception.getMessage());
} catch (BeanNotOfRequiredTypeException p_exception) {
return new ValidationErrors()
.addError("Exception thrown calling validate():"
+ p_exception.getMessage());
} catch (BeansException p_exception) {
return new ValidationErrors()
.addError("Exception thrown calling validate():"
+ p_exception.getMessage());
}
}
}
This is then configured in the database change log XML file as follows:
<changeSet id="15" author="theauthor">
<XXX:springBeanChange
changeClass="XXX.XXX.XXX.upgrade.tasks.TaskUpgrade" />
</changeSet>
Where TaskUpgrade implements CustomTaskChange and is the class that is returned get the call to getBean in SpringBeanChange.
The database change log file also contains many 'normal' liquibase commands such as addColumn.
A custom Java class has then been written which actually performs the upgrade (the following lines show the important lines of code which actually do the upgrade). This Java program is manually executed after the application has been deployed onto the server:
Liquibase liquibase =
new Liquibase(getChangeLogFile(), new ClassLoaderResourceAccessor(), new JdbcConnection(conn));
if ("update".equalsIgnoreCase(command)) {
liquibase.update(contexts);
} else {
throw new IllegalArgumentException("Unknown command " + command);
}
This works fine and executes the database upgrade.
I'm looking to avoid the need to use the custom Java program to perform the upgrade and actually do it when the application starts up. The app already uses Spring so it makes sense to to the upgrade when the Spring context is initialising.
To do this, I've added the following to the applicationContext file:
<bean id="myLiquibase" class="liquibase.integration.spring.SpringLiquibase">
<property name="dataSource" ref="dataSource" />
<property name="changeLog" value="classpath:databaseChangeLog.xml" />
<property name="contexts" value="test, production" />
</bean>
However, when the application starts up, I get the following exception:
2014-03-25 13:02:16,097 [main] ERROR context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myLiquibase' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is liquibase.exception.ChangeLogParseException: Invalid Migration File: Unknown Liquibase extension: springBeanChange. Are you missing a jar from your classpath?
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1488)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:549)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1282)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:518)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:499)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:224)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at XXX.XXX.XXX.demo.YYYDemo.main(YYYDemo.java:47)
Caused by: liquibase.exception.ChangeLogParseException: Invalid Migration File: Unknown Liquibase extension: springBeanChange. Are you missing a jar from your classpath?
at liquibase.parser.core.xml.XMLChangeLogSAXParser.parse(XMLChangeLogSAXParser.java:133)
at liquibase.Liquibase.update(Liquibase.java:129)
at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:291)
at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:258)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1547)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1485)
... 22 more
Caused by: org.xml.sax.SAXException: Unknown Liquibase extension: springBeanChange. Are you missing a jar from your classpath?
at liquibase.parser.core.xml.XMLChangeLogSAXHandler.startElement(XMLChangeLogSAXHandler.java:495)
at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
at org.apache.xerces.parsers.AbstractXMLDocumentParser.emptyElement(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.emptyElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at liquibase.parser.core.xml.XMLChangeLogSAXParser.parse(XMLChangeLogSAXParser.java:99)
... 27 more
Caused by: org.xml.sax.SAXException: Unknown Liquibase extension: springBeanChange. Are you missing a jar from your classpath?
at liquibase.parser.core.xml.XMLChangeLogSAXHandler.startElement(XMLChangeLogSAXHandler.java:359)
... 39 more
I can't find anything on the Liquibase site or anywhere else which provides any help as to what JAR I'm missing (if indeed I am missing one) or if anything else is missing/not defined.
Does anyone have any ideas?
Thanks in advance.
The jar that contains the custom extension is what is missing from your classpath. I don't use Spring, so I don't know how it sets up the classpath, but you probably need to either put the jar in a standard location so Spring can find it or else configure the Spring classpath.

Resources