SpringJMS etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
SpringJMS etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

2 Mayıs 2023 Salı

SpringJMS ActiveMQ Kullanımı

Maven
Şöyle yaparız
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
Producer
Örnek
Elimizde şöyle bir kod olsun
import org.apache.activemq.ActiveMQConnectionFactory;
@Configuration
@EnableJms
public class MQConfigHelper {
  final String BROKER_URL = "tcp://localhost:61616";
  //Enter your ActiveMQ password and username
  final String BROKER_USERNAME = "";
  final String BROKER_PASSWORD = "";

  @Bean
  public ActiveMQConnectionFactory activemqConnectionFactory() {
    ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
    factory.setTrustAllPackages(true);
    factory.setBrokerURL(BROKER_URL);
    factory.setPassword(BROKER_USERNAME);
    factory.setUserName(BROKER_PASSWORD);
    return factory;
  }
  @Bean
  public MessageConverter messageConverter() {
    MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
    converter.setTargetType(MessageType.TEXT);
    return converter;
  }
  @Bean
  public JmsTemplate templateConfig() {
    JmsTemplate jmsTemplate = new JmsTemplate();
    jmsTemplate.setConnectionFactory(activemqConnectionFactory());
    jmsTemplate.setMessageConverter(messageConverter());
    jmsTemplate.setDeliveryPersistent(true);
    return jmsTemplate;
  }
}
Mesaj gönderen taraf şöyledir
public class CarOrder {...}

public class CustomerOrder {...}

import org.springframework.jms.core.JmsTemplate;
import javax.jms.TextMessage;

@Component
public class MessageSender {
  String queueName = "carQueue";
  @Autowired
  JmsTemplate jmsTemplate;
  public void sendToQueue() {
   try {
     CarOrder carOrder = new CarOrder("Mercedes GLE", 7, 74);
     processMessageForSending(carOrder);
    } catch (Exception e) {
      ...
    }
  }
  public void processMessageForSending(Object message) 
  throws JsonProcessingException {
    String jsonObj = new ObjectMapper()
      .writer()
      .withDefaultPrettyPrinter()
      .writeValueAsString(message);
      jmsTemplate.send(queueName, messageCreator -> {
        TextMessage txtMessage = messageCreator.createTextMessage();
        txtMessage.setText(jsonObj);
        return txtMessage;
      });
  }
}
Mesaj dinleyen taraf şöyledir
import org.springframework.jms.annotation.JmsListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;
@Component
public class MessageConsumer {
  @JmsListener(destination = "carQueue")
  public void queueMessageReceiver(Message receivedMessage) {
    try {
      processMessageReceived(receivedMessage);
    } catch (Exception e) {
       ...
    }
  }
  public void processMessageReceived(Message messageArg) throws JMSException {
    if (messageArg instanceof TextMessage) {
      TextMessage textMessage = (TextMessage) messageArg;
      String processedMessage = textMessage.getText();
      ... 
     }
  }
}

31 Ağustos 2021 Salı

SpringJMS Kullanımı

Giriş
Producer ve Consumer arasındaki kullanılacak mesaj formatını belirlenir. 
- JSON seçilebilir.
Bu durumda Producer şöyledir
Gson gson = new Gson();
String jsonPerson = gson.toJson(person);

jmsTemplate.convertAndSend(destinationTopic, jsonPerson);
Bu durumda Consumer şöyledir
@JmsListener(...)
public void listen(String mensagem) {
  Person person = new Person();
  try {
    Gson gson = new Gson();
    person = gson.fromJson(mensagem, Person.class);
    ...
  }catch(Exception e){
    ...
  }
}

Producer
1. @EnableJms tanımlanır
2. ActiveMQConnectionFactory bean yaratılır
2. JmsTemplate bean yaratılır

Consumer
1. @EnableJms tanımlanır
2. ActiveMQConnectionFactory bean yaratılır
3. JmsListenerContainerFactory  bean yaratılır. Bu arayüzü gerçekleştiren sınıf DefaultJmsListenerContainerFactory 
4. @JmsListener ile mesajları işleyecek kod belirtilir.


27 Aralık 2020 Pazar

SpringJMS JmsListenerConfigurer Arayüzü

Giriş
Şu satırı dahil ederiz
import org.springframework.jms.annotation.JmsListenerConfigurer;
Açıklaması şöyle. Yani @JmsListener anotasyonunu kullanmak daha kolay :)
Optional interface to be implemented by a Spring managed bean willing to customize how JMS listener endpoints are configured. Typically used to define the default JmsListenerContainerFactory to use or for registering JMS endpoints in a programmatic fashion as opposed to the declarative approach of using the @JmsListener annotation.
configureJmsListeners metodu
Örnek
Elimizde şöyle bir kod olsun
@Component
public class QueueService implements MessageListener {
  @Autowired
  private JmsTemplate jmsTemplate;
  public void send(String destination, String message) {
    jmsTemplate.convertAndSend(destination, message);
  }
  @Override
  public void onMessage(Message message) {
    if (message instanceof ActiveMQTextMessage) {
      ActiveMQTextMessage textMessage = (ActiveMQTextMessage) message;
      try {
        LOGGER.info("Completed task " + textMessage.getText());
      } catch (InterruptedException | JMSException e) {
        e.printStackTrace();
      }
    } else {
      LOGGER.error("Message is not a text message " + message.toString());
    }
  }
}
Şöyle yaparız
@SpringBootApplication
@EnableJms
public class SpringBootApplication implements JmsListenerConfigurer {
  @Autowired
  private QueueService queueService;
  
  public static void main(String[] args) {
    SpringApplication.run(SpringBootApplication.class, args);
  }
  
  @Override
  public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
    SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
    endpoint.setId("myId");
    endpoint.setDestination("queueName");
    endpoint.setMessageListener(queueService);
    registrar.registerEndpoint(endpoint);
  }
}
Örnek
Şöyle yaparız
@SpringBootApplication
@EnableJms
public class SpringBootApplication implements JmsListenerConfigurer {
  @Autowired
  private QueueService queueService;
  public static void main(String[] args) {
    SpringApplication.run(SpringBootApplication.class, args);
  }

  @Override
  public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
    SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
    endpoint.setId("myId");
    endpoint.setDestination("queueName");
    endpoint.setMessageListener(queueService);
    registrar.registerEndpoint(endpoint);
  }
}

24 Ağustos 2020 Pazartesi

SpringJMS JmsTemplate Sınıfı

Giriş
Şu satırı dahil ederiz. Bu sınıf hem yazma hem de okuma için kullanılabilir. Ancak okuma için tercih senkron çalıştığı için edilmiyor.
import org.springframework.jms.core.JmsTemplate;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
constructor
Şöyle yaparız.
JmsTemplate jmsTemplate = new JmsTemplate();
browse metodu
Şöyle yaparız.
int count = this.jmsTemplate.browse(queue_name, new BrowserCallback<Integer>() {
  public Integer doInJms(final Session session, final QueueBrowser browser)
  throws JMSException {
    Queue queue1 = browser.getQueue();
    Enumeration enumeration = browser.getEnumeration();
    int counter = 0;
    while (enumeration.hasMoreElements()) {
      Message msg = (Message) enumeration.nextElement();
      ...
      counter += 1;
    }
    return counter;
  }
});
convertAndSend metodu
convertAndSend() metodu metodları ilk parametre olarak ya "queue name" ya da Destinaton nesnesi alır. Bu parametreye göre overload edilmiş bir sürü convertAndSend() metodu var.

convertAndSend metodu - Queue Name + Object
Örnek
Şöyle yaparız.
JmsTemplate template = ...
Foo foo = new Foo(...);

template.convertAndSend("my-destination", foo);
convertAndSend metodu - Queue Name + Object + MessagePostProcessor
Örnek
Mesajı biraz gecikme ile gödermek için şöyle yaparız
jmsTemplate.convertAndSend(queue, message, new MessagePostProcessor() {
  @Override
  public Message postProcessMessage(Message msg) throws JMSException {
    msg.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, 10000);
    return msg;
  }
});
convertAndSend metodu - Destination + Object
Örnek
Şöyle yaparız.
TextMessage txtMsg = ...;

Destination destQ = ...

jmsTemplate.convertAndSend(destQ, txtMsg);
convertAndSend metodu - Queue Name + Object + int
Şöyle yaparız.
int waitSecs = rand.nextInt(3);
jmsTemplate.convertAndSend("YourQueueName", new Foo(...), waitSecs);
execute metodu
Şöyle yaparız.
Boolean result = hmsTemplate.execute(new SessionCallback<Boolean>() {

  @Override
  public Boolean doInJms(Session session) throws JMSException {
    Topic topic = ((AQjmsSession) session).getTopic(...);
    ((AQjmsTopicPublisher) publisher).publish(topic,
      topicSession.createTextMessage(message),recipientL ist1);
    return true;
  }
});
getDestinationResolver metodu
Belirtilen isme sahip kuyruğu döndürür. Şöyle yaparız.
Destination replyToQName = jmsTemplate.getDestinationResolver()
  .resolveDestinationName(session, responseQueueName, false);
receiveSelected metodu
Şöyle yaparız.
Destination responseQ = ...
String filter = "..." ; 
TextMessage respMsg = (TextMessage) jmsTemplate.receiveSelected(responseQ, filter);
send metodu - topic + MessageCreator
Örnek
Şöyle yaparız
@Autowired
private JmsTemplate jms;

public void sendTicket(Reservation reservation) {

  // Send a message
  jms.send("mailbox-destination", new MessageCreator() {
    public ObjectMessage createMessage(Session session) throws JMSException {
      ObjectMessage message = session.createObjectMessage();
      message.setObject(reservation);
      return message;
    }
  });
}
Örnek
Şöyle yaparız. MessageCreator olarak lambda kullanılıyor.
String msg = ...;
msTemplate.send(destinationName, session -> {
  Message message = session.createTextMessage(msg);
  LOGGER.info(message.getJMSCorrelationID());
  LOGGER.info(message.getJMSMessageID());
  return message;
});
setConnectionFactory metodu
Örnek
Şöyle yaparız.
ConnectionFactory connectionFactory = ...;
jmsTemplate.setConnectionFactory(connectionFactory);
Örnek
"Oracle Advanced Queueing" kullanan elimizde şöyle bir kod olsun.
@Bean
DataSource dataSource() throws SQLException {
  OracleDataSource dataSource = new OracleDataSource();
  dataSource.setUser("yourusername");
  dataSource.setPassword("yourpassword");
  dataSource.setURL("jdbc:oracle:thin:@yourserver:1521:xe");
  dataSource.setImplicitCachingEnabled(true);
  dataSource.setFastConnectionFailoverEnabled(true);
  return dataSource;
}    

@Bean
public QueueConnectionFactory connectionFactory() throws Exception {
  return AQjmsFactory.getQueueConnectionFactory(dataSource());
}
Şöyle yaparız.
jmsTemplate.setConnectionFactory(connectionFactory());
setDeliveryDelay metodu
Şöyle yaparız
long deliveryDelay = ...;
jmsTemplate.setDeliveryDelay(deliveryDelay);
jmsTemplate.convertAndSend(queue.getName(), event);
setDeliveryMode metodu
Şöyle yaparız.
jmsTemplate.setDeliveryMode(DeliveryMode.PERSISTENT);
setMessageConverter metodu
Açıklaması şöyle
The default conversion strategy used by JmsTemplate for both ConvertAndSend() and ReceiveAndConvert() operations is the SimpleMessageConverter class.

The SimpleMessageConverter is able to handle TextMessages, BytesMessages, MapMessages, and ObjectMessages. This class implements the MessageConverter interface.

Apart from SimpleMessageConverter, Spring JMS provides some other MessageConverter classes out of the box like MappingJackson2MessageConverter, MarshallingMessageConverter, MessagingMessageConverter.
Örnek - MappingJackson2MessageConverter 
Elimizde şöyle bir kod olsun.
@Bean
public MessageConverter jacksonJmsMessageConverter() {
  MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
  converter.setTargetType(MessageType.TEXT);
  converter.setTypeIdPropertyName("_type");
  return converter;
}
Şöyle yaparız.
jmsTemplate.setMessageConverter(jacksonJmsMessageConverter());
setPubSubDomain metodu
Şöyle yaparız.
jmsTemplate.setPubSubDomain(true);
setReceiveTimeout metodu
Şöyle yaparız.
jmsTemplate.setReceiveTimeout(30000L);
setSessionAcknowledgeMode metodu
Şöyle yaparız.
jmsTemplate.setSessionAcknowledgeMode(Session.SESSION_TRANSACTED);
setSessionTransacted metodu
Şöyle yaparız.
jmsTemplate.setSessionTransacted(true);