Spring boot application does not start when ActiveMQ failover transport fails - java

I want my Spring Boot application to start regardless if it can connect to JMS or not. I have this minimal example:
#SpringBootApplication
#EnableJms
public class JmsActivemqFailoverApplication {
public static void main(String[] args) {
SpringApplication.run(JmsActivemqFailoverApplication.class, args);
}
#Component
public static class JmsReceiver {
#JmsListener(destination = "inbox")
public void receive(Message message) {
System.out.println("Received <" + message + ">");
}
}
#RestController
public static class HelloWorldController {
#GetMapping("/")
public String helloWorld() {
return "Hello world";
}
}
}
when application.properties contains:
spring.activemq.broker-url=tcp://non-existing-broker:61616
I can get response from helloWorld endpoint. When I change property to:
spring.activemq.broker-url=failover:(tcp://non-existing-broker:61616)
Application keeps trying to connect to broker and I can not get response from my REST endpoint.
Please advice, how can I have application running without waiting for ActiveMQ Failover transport to succeed.
Example code available at https://github.com/madoxas/jms-activemq-failover

One way to achieve this is:
Disable automatic JMS container startup with property spring.jms.listener.auto-startup=false
Start JMS container after application has started:
#Component
public class JmsStarter implements ApplicationRunner {
private final JmsListenerEndpointRegistry jmsRegistry;
public JmsStarter(JmsListenerEndpointRegistry jmsRegistry) {
this.jmsRegistry = jmsRegistry;
}
#Override
public void run(ApplicationArguments args) {
for (MessageListenerContainer listenerContainer : jmsRegistry.getListenerContainers()) {
listenerContainer.start();
}
}
}

Related

Netty as WebSocket server not starting in SpringBootTest

I'm trying to write a simple WebSocket server app based on on Spring and Netty.
My application looks like this
#SpringBootApplication
public class DemoReactiveWSApp {
public static void main(String[] args) {
SpringApplication.run(DemoReactiveWSApp.class, args);
}
}
with the following configuration
#Configuration
public class WebSocketConfig {
#Bean
public HandlerMapping handlerMapping() {
final Map<String, WebSocketHandler> handlerMap = new HashMap<>();
// will be populated later with routes and handlers
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setUrlMap(handlerMap);
mapping.setOrder(-1);
return mapping;
}
#Bean
public RequestUpgradeStrategy requestUpgradeStrategy() {
return new ReactorNettyRequestUpgradeStrategy();
}
}
When I run it, everything boots up, and I can attempt (for now) to establish WS connection.
However, when I want to start it in a test
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DemoReactiveWSAppTest {
#LocalServerPort
private String port;
#Test
public void givenContext_WhenStartingApplication_ThenItLoads() throws InterruptedException {
System.out.println("Port: " + port);
}
}
the server never seems to boot.
Am I forgetting something?
Stupid me, I forgot #RunWith(SpringRunner.class)

Can I launch a telegram bot from a Spring Boot application?

I try to create a bot from here
https://github.com/rubenlagus/TelegramBots
It works as a simple application, but when I try to add Spring Boot it doesn't work. I suppose it is because Spring Boot launches Tomcat and telegram bot tries to send/recieve some http.
I don't get any errors (bot launches as #Component bean).
Is it even possible to connect this kind of bot and a Spring Boot app or at least a web application?
You can try to use telegrambots-spring-boot-starter from the same library.
Your main configuration should looks like:
#SpringBootApplication
public class YourApplicationMainClass {
public static void main(String[] args) {
ApiContextInitializer.init();
SpringApplication.run(YourApplicationMainClass.class, args);
}
}
And class of your bot:
// Standard Spring component annotation
#Component
public class YourBotName extends TelegramLongPollingBot {
//Bot body.
}
A bit more information you can find here https://github.com/rubenlagus/TelegramBots/tree/master/telegrambots-spring-boot-starter
As #Bobby said, you can try the
telegrambots-spring-boot-starter project
And also you can add the new telegrambots-extensions dependency which make you able to manage command bot.
So the code will be
#Component
public class Foo extends TelegramLongPollingCommandBot {
#Override
public void processNonCommandUpdate(Update update) {
Also you can manage the command in this way.
#Component
public class FooCommand extends DefaultBotCommand {
#Override
public void execute(AbsSender absSender, User user, Chat chat, Integer messageId, String[] arguments) {
You can register your TelegramLongPollingCommandBot within the SpringBoot class main, as below:
#SpringBootApplication
public class TelegramBotConfiguration {
public static void main(String[] args) {
ApiContextInitializer.init();
TelegramBotsApi telegramBotsApi = new TelegramBotsApi();
try {
session = telegramBotsApi.registerBot(new Foo());
} catch (TelegramApiException e) {
log.error(e);
}
SpringApplication.run(TelegramBotConfiguration.class, args);
}
}
(https://github.com/rubenlagus/TelegramBots/tree/master/telegrambots-extensions)

Spring Integration manually publish message to channel

I'm in the process of learning how to use the Java Spring Framework and started experimenting with Spring Integration. I'm trying to use Spring Integration to connect my application to an MQTT broker both to publish and subscribe to messages but I'm having trouble finding a way to manually publish messages to an outbound channel. If possible I want to build it using notations in the java code exclusively rather than xml files defining beans and other related configuration.
In every example I've seen the solution to manually publishing a message seems to be to use a MessagingGateway Interface and then use the SpringApplicationBuilder to get the ConfigurableApplicationContext to get a reference to the gateway interface in the main method. The reference is then used to publish a message. Would it be possible to use AutoWired for the interface instead? In my attempts I just get a NullPointer.
My aim is to build a game where I subscribe to a topic to get game messages and then whenever the user is ready to make the next move, publish a new message to the topic.
Update:
This is one of the examples I've been looking at of how to setup an outbound channel: https://docs.spring.io/spring-integration/reference/html/mqtt.html
Update 2 after answer from Gary Russel:
This is some example code I wrote after looking at examples which gets me a NullPointer when using #AutoWired for the Gateway when running gateway.sendToMqtt in Controller.java. What I want to achieve here is to send an mqtt message manually when a GET request is handled by the controller.
Application.java
#SpringBootApplication
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
Controller.java
#RestController
#RequestMapping("/publishMessage")
public class Controller {
#Autowired
static Gateway gateway;
#RequestMapping(method = RequestMethod.GET)
public int request(){
gateway.sendToMqtt("Test Message!");
return 0;
}
}
MqttPublisher.java
#EnableIntegration
#Configuration
public class MqttPublisher {
#Bean
public MqttPahoClientFactory mqttClientFactory(){
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
factory.setServerURIs("tcp://localhost:1883");
return factory;
}
#Bean
#ServiceActivator(inputChannel = "mqttOutboundChannel")
public MessageHandler mqttOutbound(){
MqttPahoMessageHandler messageHandler =
new MqttPahoMessageHandler("clientPublisher", mqttClientFactory());
messageHandler.setAsync(true);
messageHandler.setDefaultTopic("topic");
return messageHandler;
}
#Bean
public MessageChannel mqttOutboundChannel(){
return new DirectChannel();
}
#MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface Gateway {
void sendToMqtt(String data);
}
}
Update:
Not sure if this is the proper logging but it is what I get from adding:
logging.level.org.springframework.web=Debug
logging.level.org.hibernate=Error
to application.properties.
https://hastebin.com/cuvonufeco.hs
Use a Messaging Gateway or simply send a message to the channel.
EDIT
#SpringBootApplication
public class So47846492Application {
public static void main(String[] args) {
SpringApplication.run(So47846492Application.class, args).close();
}
#Bean
public ApplicationRunner runner(MyGate gate) {
return args -> {
gate.send("someTopic", "foo");
Thread.sleep(5_000);
};
}
#Bean
#ServiceActivator(inputChannel = "toMqtt")
public MqttPahoMessageHandler mqtt() {
MqttPahoMessageHandler handler = new MqttPahoMessageHandler("tcp://localhost:1883", "foo",
clientFactory());
handler.setDefaultTopic("myTopic");
handler.setQosExpressionString("1");
return handler;
}
#Bean
public MqttPahoClientFactory clientFactory() {
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
factory.setUserName("guest");
factory.setPassword("guest");
return factory;
}
#Bean
public MqttPahoMessageDrivenChannelAdapter mqttIn() {
MqttPahoMessageDrivenChannelAdapter adapter =
new MqttPahoMessageDrivenChannelAdapter("tcp://localhost:1883", "bar", "someTopic");
adapter.setOutputChannelName("fromMqtt");
return adapter;
}
#ServiceActivator(inputChannel = "fromMqtt")
public void in(String in) {
System.out.println(in);
}
#MessagingGateway(defaultRequestChannel = "toMqtt")
public interface MyGate {
void send(#Header(MqttHeaders.TOPIC) String topic, String out);
}
}

Send and get information for Restfull and Spring

I am beginner with spring - boot and webservice, I have two exercises to do, they would know How to implement the client and the run () method; to send and receive strings trough In this webservice?
PROJECT CONSUMER
public class Service implements Runnable {
public static void main(String args[]) {
System.out.println("Send the messages....");
Thread thread = new Thread(new Service());
thread.start();
}
public void run() {
// Loop receiving messages
}
}
PROJECT PRODUCER
#Path("/greet")
#Component
public class GreetResource {
static Logger logger = LoggerFactory.getLogger(GreetResource.class);
#Autowired
Client client;
public GreetResource() {
logger.info("Resource Initialized");
}
#GET
#Path("/echo/{msg}")
#Produces({ MediaType.TEXT_PLAIN_VALUE })
public Response echo(#PathParam("msg") String message) {
return Response.ok().entity(message).build();
}
#POST
#Path("/send")
#Consumes({ MediaType.TEXT_PLAIN_VALUE })
public boolean sendMessage(String greeting) {
client.sendAMessage(greeting);
return true;
}
}
PROJECT PRODUCER
#EnableAutoConfiguration
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
#Autowired
private Environment env;
#PostConstruct
public void initApplication() throws IOException {
if (env.getActiveProfiles().length == 0) {
logger.warn("No Spring profile configured, running with default configuration");
} else {
logger.info("Running with Spring profile(s) : {}", Arrays.toString(env.getActiveProfiles()));
Collection<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
if (activeProfiles.contains("dev") && activeProfiles.contains("prod")) {
logger.error("You have misconfigured your application! "
+ "It should not run with both the 'dev' and 'prod' profiles at the same time.");
}
}
}
public static void main(String[] args) {
logger.info("weather application service starting...");
SpringApplication.run(Application.class, args);
}
}
PROJECT PRODUCER
import org.springframework.stereotype.Component;
#Component
public class Client {
public boolean sendAMessage(String greeting) {
// Send the message
return false;
}
}
Any tips to implement method run () and sendAMessage()?
If you are using Spring Boot and want to implement web-service , then easiest way is to implement web service using RESTapi.
You can use #ResponseBody or #RestController annotations to expose service.

Aspect does not get triggered in the context of listening for a RabbitMQ message

The FailedMessageAspect.afterMethod() below gets called successfully during RabbitConsumerMain.main() below. However, it doesn't get called when it's used in the context of listening for a RabbitMQ message - when MessageHandlerImpl.handleMesasge() receives a message from a RabbitMQ queue. Any idea why?
FailedMessageAspect.java
#Aspect
#Component
public class FailedMessageAspect {
#AfterReturning("execution(* com..MessageHandlerImpl.testAspect(..))")
private void afterMethod() {
System.out.println("aspect foo");
}
}
MessageHandlerImpl.java
#Component
public class MessageHandlerImpl implements MessageHandler {
#Override
public void testAspect() {
System.out.println("handler foo");
}
#Override
public void handleMessage(String message) {
// handleMessage is called successfully when message is received
testAspect();
// FailedMessageAspect.afterMethod() does not get called
}
}
RabbitConsumerMain.java
#Controller
#SpringBootApplication
public class RabbitConsumerMain implements CommandLineRunner {
#Autowired
private MessageHandler messageHandler;
public static void main(String[] args) throws Exception {
SpringApplication.run(RabbitConsumerMain.class, args);
}
#Override
public void run(String... args) {
messageHandler.testAspect();
//FailedMessageSpect.afterMethod() gets called right here
}
}
ConsumerConfiguration.java
#Configuration
public class ConsumerConfiguration {
#Autowired #Lazy
private MessageHandler messageHandler;
//other standard AMQP configs
#Bean
public MessageListenerContainer messageListenerContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
container.setQueues(workQueue());
MessageListenerAdapter adapter = new MessageListenerAdapter(messageHandler, new Jackson2JsonMessageConverter());
container.setMessageListener(adapter);
return container;
}
}
You don't show all your configuration but, just to be clear, Spring AOP does not advise internal method calls such as handleMessage calling testAspect() within the same class instance.
You need to use AspectJ for that; otherwise, all methods you advise must be public methods invoked via bean definitions, so Spring can invoke the method via a proxy. Internal calls within a bean are never advised.
See the reference manual for a complete explanation.

Categories

Resources