Skip to content

0. обновлённый пример без naming

Для перехода от Jakarta Naming (JNDI) к более современному подходу нам нужно модифицировать код. В основном это затронет настройку подключений и внедрение ресурсов. Давайте изменим файлы:

  1. Сначала обновим pom.xml, удалив устаревшую зависимость:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>jms-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jakarta.jakartaee-api.version>10.0.0</jakarta.jakartaee-api.version>
        <wildfly.version>27.0.0.Final</wildfly.version>
    </properties>
    <dependencies>
        <!-- Jakarta EE API -->
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>${jakarta.jakartaee-api.version}</version>
            <scope>provided</scope>
        </dependency>
        <!-- JMS API -->
        <dependency>
            <groupId>jakarta.jms</groupId>
            <artifactId>jakarta.jms-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- WildFly Remote Client -->
        <dependency>
            <groupId>org.wildfly</groupId>
            <artifactId>wildfly-client-all</artifactId>
            <version>${wildfly.version}</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>jms-demo</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
  1. JMSProducer.java остается практически без изменений, так как он уже использует CDI для внедрения ресурсов:
package com.example.jms;

import jakarta.annotation.Resource;
import jakarta.jms.*;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Logger;
import java.util.logging.Level;

@WebServlet("/producer")
public class JMSProducer extends HttpServlet {
    private static final Logger LOGGER = Logger.getLogger(JMSProducer.class.getName());

    @Resource(lookup = "java:/ConnectionFactory")
    private ConnectionFactory connectionFactory;

    @Resource(lookup = "java:/jms/queue/ExampleQueue")
    private Queue queue;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();

        try {
            Connection connection = connectionFactory.createConnection();
            try {
                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                MessageProducer producer = session.createProducer(queue);

                TextMessage message = session.createTextMessage(
                    "Демо сообщение JMS: " + java.time.LocalDateTime.now()
                );
                message.setStringProperty("sender", "JMSProducerServlet");
                message.setIntProperty("priority", 5);

                producer.setDeliveryMode(DeliveryMode.PERSISTENT);
                producer.send(message);

                LOGGER.info("Сообщение отправлено: " + message.getText());
                out.println("Сообщение успешно отправлено в очередь");

                producer.close();
                session.close();
                connection.close();
            } catch (JMSException e) {
                LOGGER.log(Level.SEVERE, "Ошибка JMS", e);
                out.println("Ошибка при отправке сообщения: " + e.getMessage());
                throw new ServletException(e);
            }
        } catch (JMSException e) {
            LOGGER.log(Level.SEVERE, "Ошибка соединения", e);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 
                             "Не удалось установить JMS-соединение");
        }
    }

    public void sendMessage(String messageText) throws JMSException {
        Connection connection = connectionFactory.createConnection();
        try {
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer producer = session.createProducer(queue);
            TextMessage message = session.createTextMessage(messageText);
            producer.send(message);
        } finally {
            connection.close();
        }
    }
}
  1. JMSConsumer.java также остается похожим:
package com.example.jms;

import jakarta.annotation.Resource;
import jakarta.jms.*;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/consumer")
public class JMSConsumer extends HttpServlet {

    @Resource(lookup = "java:/ConnectionFactory")
    private ConnectionFactory connectionFactory;

    @Resource(lookup = "java:/jms/queue/ExampleQueue")
    private Queue queue;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();

        try (Connection connection = connectionFactory.createConnection();
             Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {

            connection.start();
            MessageConsumer consumer = session.createConsumer(queue);

            Message message = consumer.receive(5000);
            if (message instanceof TextMessage textMessage) {
                out.println("Получено сообщение: " + textMessage.getText());
            } else {
                out.println("Сообщений нет");
            }
        } catch (JMSException e) {
            throw new ServletException(e);
        }
    }
}
  1. JMSStandaloneClient.java требует наибольших изменений, так как использовал JNDI напрямую:
package com.example.jms;

import jakarta.jms.*;
import java.util.Properties;
import org.wildfly.common.function.ExceptionSupplier;
import org.wildfly.security.auth.client.*;
import javax.security.auth.callback.CallbackHandler;
import org.wildfly.security.auth.client.AuthenticationConfiguration;
import org.wildfly.security.auth.client.AuthenticationContext;
import org.wildfly.security.auth.client.MatchRule;

public class JMSStandaloneClient {
    public static void main(String[] args) {
        try {
            // Настройка аутентификации
            AuthenticationConfiguration authConfig = AuthenticationConfiguration.empty()
                .useName("admin")
                .usePassword("password");

            AuthenticationContext context = AuthenticationContext.empty()
                .with(MatchRule.ALL, authConfig);

            // Установка контекста аутентификации
            AuthenticationContext.getContextManager().setGlobalDefault(context);

            // Создание фабрики подключений через WildFly Connector
            RemoteConnectionFactory connectionFactory = new RemoteConnectionFactory();

            // Создание соединения
            try (JMSContext jmsContext = connectionFactory.createContext("admin", "password")) {

                // Создание очереди
                Queue queue = jmsContext.createQueue("java:/jms/queue/ExampleQueue");

                // Получение сообщения
                JMSConsumer consumer = jmsContext.createConsumer(queue);
                String message = consumer.receiveBody(String.class, 5000);

                if (message != null) {
                    System.out.println("Получено сообщение: " + message);
                } else {
                    System.out.println("Сообщений нет");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Основные изменения: 1. Удалили зависимость jakarta.naming-api 2. В standalone клиенте заменили JNDI на прямое создание подключения через WildFly Connector 3. Используем JMSContext вместо старого подхода с Connection/Session 4. Аутентификация теперь происходит через WildFly Security 5. Упростили работу с очередями используя современный API

web.xml остается без изменений, так как он не связан с JNDI напрямую.

Эти изменения делают код более современным и соответствующим текущим рекомендациям Jakarta EE.

пример

https://gitlab.com/javaee5603144/examples/-/tree/main/jms-demo?ref_type=heads