I have a problem in Spring such that I get the next error when I try to export two services from server to client:
Caused by: org.springframework.remoting.RemoteLookupFailureException: Could not find RMI service [rmi://localhost:1099/ClientsService] in RMI registry; nested exception is java.rmi.NotBoundException: ClientsService
This is my Configuration in the server side:
#Configuration
public class ClientsServerConfig {
#Bean
RmiServiceExporter rmiServiceExporter() {
RmiServiceExporter rmiServiceExporter = new RmiServiceExporter();
rmiServiceExporter.setServiceInterface(ClientService.class);
rmiServiceExporter.setService(clientService());
rmiServiceExporter.setServiceName("ClientsService");
return rmiServiceExporter;
}
#Bean
ClientService clientService() {
return new ClientsServiceImpl(clientRepository());
}
#Bean
RepositoryInterface<Long, Client> clientRepository() {
return new ClientDbRepository();
}
}
and
#Configuration
public class GunProviderServerConfig{
#Bean
RmiServiceExporter rmiServiceExporter() {
RmiServiceExporter rmiServiceExporter = new RmiServiceExporter();
rmiServiceExporter.setServiceInterface(GunProviderService.class);
rmiServiceExporter.setService(gunProviderService());
rmiServiceExporter.setServiceName("GunProviderService");
return rmiServiceExporter;
}
#Bean
GunProviderService gunProviderService() {
return new GunProviderServiceImpl(gunProviderRepository());
}
#Bean
RepositoryInterface<Long, GunProvider> gunProviderRepository() {
return new GunProviderDbRepository();
}
}
and this is the configuration in the client side:
#Configuration
public class ClientConfig {
#Bean
RmiProxyFactoryBean rmiProxyFactoryBean() {
RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
rmiProxyFactoryBean.setServiceUrl("rmi://localhost:1099/ClientsService");
rmiProxyFactoryBean.setServiceInterface(ClientService.class);
return rmiProxyFactoryBean;
}
#Bean
RmiProxyFactoryBean rmiProxyFactoryBean2() {
RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
rmiProxyFactoryBean.setServiceUrl("rmi://localhost:1099/GunProviderService");
rmiProxyFactoryBean.setServiceInterface(GunProviderService.class);
return rmiProxyFactoryBean;
}
And the error is caused I think because the application does not know what service to use when two are exported. If I comment "GunProviderServerConfig" and "rmiProxyFactoryBean2" such that I have only the ClientService, the app will work.
I ran into the same issue yesterday but it worked for me this morning. consider moving the two exporters to the same configuration class
Related
My requirement is to be able to listen to rabbitMq messages on two different queues. One queue receives message with content_type = text/plain and my Spring boot listener method accepts String parameter. Second queue receives message with content_type = application/json and my listener method accepts parameter of my POJO 'User' type. I am sending messages using RabbitMQ web portal. I am not able to successfully listen to both types of messages in the same spring boot listener application. Please help me to succeed in listening to both types of messages on two queues.Below is my listener class and configuraiton class code snippet.
Listener class:
#Component
public class EventListener {
public void processFirstQueue(String message) {
try {
if (message != null) {
log.info("Received the message from Queue!");
service.process(message);
}
} catch (Exception e) {
log.error("Error occurred " + e);
}
}
public void processSecondQueue(User user) {
try {
if (user!= null) {
log.info("Received the message from Queue!");
service.processUser(user);
}
} catch (Exception e) {
log.error("Error occurred " + e);
}
}
}
RabbitMqConfig.java
public class RabbitMqConfig {
#Bean(name = "rabbitmq-server")
public CachingConnectionFactory getConnectionFactory() {
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
cachingConnectionFactory.setHost("localhost");
return cachingConnectionFactory;
}
#Bean
public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames("queue1", "queue2");
container.setMessageListener(listenerAdapter);
container.setMessageConverter(new Jackson2JsonMessageConverter());
return container;
}
#Bean
public MessageListenerAdapter listenerAdapter(OutgoingEventListener receiver) {
MessageListenerAdapter listener = new MessageListenerAdapter(receiver);
Map<String, String> queueToMethodName = new HashMap<>();
queueToMethodName.put("queue1", "processFirstQueue");
queueToMethodName.put("queue2", "processSecondQueue");
listener.setQueueOrTagToMethodName(queueToMethodName);
return listener;
}
#Bean
public MessageConverter jsonMessageConverter(){
return new Jackson2JsonMessageConverter();
}
#Bean
public RabbitTemplate getRabbitTemplate(ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
}
I am able to post json message successfully to queue2 as seen in below screenshot.
But when I am posting content_type = text/plain to queue1 as seen in below screenshot, I am getting error in my Spring boot service saying content-type text is found but json is expected.
Try to add message converter for your consumer like that -
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class RabbitMqConfig {
#Bean
public MessageConverter jsonMessageConverter(){
return new Jackson2JsonMessageConverter();
}
#Bean
public SimpleRabbitListenerContainerFactory jsaFactory(ConnectionFactory connectionFactory,
SimpleRabbitListenerContainerFactoryConfigurer configurer) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
configurer.configure(factory, connectionFactory);
factory.setMessageConverter(jsonMessageConverter());
return factory;
}
}
I am new to both SOAP & spring boot technologies.However i have created soap webservice using below reference link.
https://spring.io/guides/gs/producing-web-service/
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
#Bean(name = "REL-6-MM7-1-4")
#Primary
public DefaultWsdl11Definition defaultWsdl11Definition() {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("MMSPort");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace("http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-6-MM7-1-4");
wsdl11Definition.setSchemaCollection(getXsdCollection());
return wsdl11Definition;
}
#Bean
public XsdSchemaCollection getXsdCollection() {
return new XsdSchemaCollection() {
public XsdSchema[] getXsdSchemas() {
return new XsdSchema[]{new SimpleXsdSchema(new ClassPathResource("REL-6-MM7-1-4.xsd")), new SimpleXsdSchema(new ClassPathResource("SoapEnvelope.xsd"))};
}
public XmlValidator createValidator() {
throw new UnsupportedOperationException();
}
};
}
Please find xsd posted.
This is the error that happen when you are not using the correct url into soap ui.
You need to search the right location of your XSD in the browser and make sure you can access to it.
Then you need to check the URL you are pasting into SOAP UI and see if the relative URLs actually are correct.
If they aren't, you have to use the correct location.
Edit :
In your case, I see the following code :
#Bean(name = "REL-6-MM7-1-4")
So I think that your ws is exposed at :
http://localhost:8080/ws/REL-6-MM7-1-4.wsdl
Edit 2 :
In your case, you also need to provide multiple xsd. You can do it by adding :
#Bean
public XsdSchemaCollection getXsdCollection() {
return new XsdSchemaCollection() {
public XsdSchema[] getXsdSchemas() {
return new XsdSchema[]{new SimpleXsdSchema(new ClassPathResource("REL-6-MM7-1-4.xsd")), new SimpleXsdSchema(new ClassPathResource("SoapEnvelope.xsd"))};
}
public XmlValidator createValidator() {
throw new UnsupportedOperationException();
}
};
}
and by using it at :
wsdl11Definition.setSchema(getXsdCollection());
I am using Spring Boot 1.4.1-RELEASE and RabbitMQ 3.2.3. My Application class looks like this -
#SpringBootApplication
#EnableAutoConfiguration
public class EventStoreMessageDeliveryApplication {
public final static String queueName = "customer.default.queue"; // spring-boot
#Bean
Queue queue() {
return new Queue(queueName, true);
}
#Bean
FanoutExchange exchange() {
return new FanoutExchange("customer.events.fanout.exchange", true, false); // spring-boot-exchange
}
#Bean
Binding binding() {
return new Binding(queueName, Binding.DestinationType.QUEUE, "customer.events.fanout.exchange", "*.*", null);
}
#Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
connectionFactory.setPublisherConfirms(true);
return connectionFactory;
}
#Bean
SimpleMessageListenerContainer container(MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
container.setQueueNames(queueName);
container.setMessageListener(listenerAdapter);
container.setRecoveryBackOff(new ExponentialBackOff(3000, 2));
return container;
}
#Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(EventStoreMessageDeliveryApplication.class, args);
}
}
And my listener class looks like -
#Component
public class Receiver {
private CountDownLatch latch = new CountDownLatch(1);
public void receiveMessage(String message) {
System.out.println("Received <" + message + ">");
// do something
latch.countDown();
}
public CountDownLatch getLatch() {
return latch;
}
}
I want to handle the exceptions like connection refused which may come when the broker is down. How can I handle such exceptions? I am not sure where I can get the handle for the exceptions.
You can create a SimpleRabbitListenerContainerFactory. This is basically a listener for events from RabbitConnectionFactory.
#Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setErrorHandler(rabbitErrorHandler());
return factory;
}
rabbitErrorHandler() can return a bean of implementation of org.springframework.util.ErrorHandler.
Reference docs
I have a suggestion and it could work out. Since you want to have an exception of connection refused against the RabbitMQ broker, it is up to the client to catch the exception.
In your example, which looks like the one from SpringIO docs, I would assume you could make the exception handling in the main (not recommended though):
#Component
public class Runner implements CommandLineRunner {
private final RabbitTemplate rabbitTemplate;
private final Receiver receiver;
public Runner(Receiver receiver, RabbitTemplate rabbitTemplate) {
this.receiver = receiver;
this.rabbitTemplate = rabbitTemplate;
}
#Override
public void run(String... args) throws Exception {
System.out.println("Sending message...");
try {
rabbitTemplate.convertAndSend(Application.topicExchangeName, "foo.bar.baz", "Hello from RabbitMQ!");
receiver.getLatch().await(10000, TimeUnit.MILLISECONDS);
}catch(AmqpException the_exception) {
System.out.printl("Connection refused. Problem thrown when trying to connecto the RabbitMQ");
}
}
}
The AmqpException comes from the docs of the convertAndSend() method, which is being thrown if something went bad. Here you can capture your own custom message.
I hope this is what you are looking for or atleast guides you the correct destination.
/A
I have the following class:
#Configuration
public class SpringIntegrationTest {
#Bean
public SimpleWebServiceInboundGateway testInboundGateWay (){
SimpleWebServiceInboundGateway simpleWebServiceInboundGateway = new SimpleWebServiceInboundGateway();
simpleWebServiceInboundGateway.setRequestChannelName("testChannel");
simpleWebServiceInboundGateway.setReplyChannelName("testChannel2");
return simpleWebServiceInboundGateway;
}
#Bean
public MessageChannel testChannel() {
return new DirectChannel();
}
#Bean
public MessageChannel testChannel2() {
return new DirectChannel();
}
#ServiceActivator(inputChannel = "testChannel", outputChannel = "testChannel2")
public DOMSource foo(DOMSource request) {
System.out.println("asd");
return request;
}
#Bean
public EndpointMapping soapActionEndpointMapping(SimpleWebServiceInboundGateway testInboundGateWay ) {
UriEndpointMapping uriEndpointMapping = new UriEndpointMapping();
uriEndpointMapping.setUsePath(true);
uriEndpointMapping.setEndpointMap(createEndpointMapping(testInboundGateWay ));
return uriEndpointMapping;
}
private Map<String, Object> createEndpointMapping(SimpleWebServiceInboundGateway testInboundGateWay ) {
Map<String, Object> endpointMap = new HashMap<>();
endpointMap.put("/ws/test", testInboundGateWay );
return endpointMap;
}
}
Even tough the service activator is subscribed for the "testChannel", I get the followin message:
o.s.i.w.SimpleWebServiceInboundGateway - failure occurred in gateway sendAndReceive: Dispatcher has no subscribers for channel 'org.springframework.web.context.WebApplicationContext:/MyProject restful API.testChannel'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
What am I doing wrong?
You need to add #EnableIntegration to one of your configuration classes.
Adding a dispatcher to the testChannel would fix this issue.
I am using spring boot as per examples for TcpInboundGateway, but have discovered the behaviour is slightly different than a hand coded a piece of TCP code I am replacing.
Specifically when using netcat, nc exits before receiving an answer, because the TcpInboundGateway read steam is closed, before any write occurs, causing nc to exit.
Can closing the read stream be delayed until the write has completed?
Here is the code:
#Configuration
#EnableIntegration
#ComponentScan
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = SpringApplication.run(Application.class);
}
#Bean
TcpNetServerConnectionFactory cf () {
return new TcpNetServerConnectionFactory(9876);
}
#Bean
TcpInboundGateway tcpGate() {
TcpInboundGateway gateway = new TcpInboundGateway();
gateway.setConnectionFactory(cf());
gateway.setRequestChannel(requestChannel());
return gateway;
}
#Bean
public MessageChannel requestChannel() {
return new DirectChannel();
}
#MessageEndpoint
public static class Echo {
#ServiceActivator(inputChannel = "requestChannel")
public String echo(byte [] in) {
return "echo: " + new String(in);
}
}
#Autowired
private Environment env;
}
So I figured out it was probably the stream terminator character. Did some fiddling and found that using ByteArrayRawSerializer solves my problem.
#Bean TcpNetServerConnectionFactory cf () {
TcpNetServerConnectionFactory tcpNetServerConnectionFactory = new TcpNetServerConnectionFactory(9876);
tcpNetServerConnectionFactory.setDeserializer(new ByteArrayRawSerializer());
return tcpNetServerConnectionFactory;
}