EJB 시스템에서 JMS를 사용하여 비동기적으로 메일 보내기

EJB 중에는 Bean, Entity Bean, Session Bean, Message Bean 세 가지가 있는데 그 중에서 Message Bean은 메시지를 보내는 데 쓰인다.서버: JBoss 4.2
EJB는 두 가지 유형의 메시지를 지원합니다. 하나는 Topic이고 하나는 Queue입니다.Topic: 발표/구독 방식을 바탕으로 여러 명의 수용자를 허용하고 메시지 생산자가 메시지를 테마에 보낼 수 있으며 수용자는 반드시 이 테마를 먼저 구독해야 한다.Queue: 점대점의 방식은 한 수용자에게 한 번만 받아들일 수 있으며, 메시지 생산자는 메시지를 대기열에 보낼 수 있으며, 구독할 필요가 없습니다.
JBoss에서 JMS를 사용하려면 1.% 파일을 구성해야 합니다.JBOSS_HOME%\server\default\deploy 메일 서비스.xml, 이 파일은 이메일을 보내는 매개 변수를 설정하는 데 사용됩니다. (예를 들어 gmail 서버 사용)
<?xml version="1.0" encoding="UTF-8"?>
<server>
  <mbean code="org.jboss.mail.MailService"
         name="jboss:service=Mail">
    <attribute name="JNDIName">java:/Mail</attribute>
    <attribute name="User">zoucailong</attribute>
    <attribute name="Password">******</attribute>
    <attribute name="Configuration">
      <!-- A test configuration -->
      <configuration>
        <!-- Change to your mail server prototocol -->
        <property name="mail.store.protocol" value="pop3"/>
        <property name="mail.transport.protocol" value="smtp"/>
        <!-- Change to the user who will receive mail  -->
        <property name="mail.user" value="zoucailong"/>
        <!-- Change to the mail server  -->
        <property name="mail.pop3.host" value="pop3.gmail.com"/>
        <!-- Change to the SMTP gateway server -->
        <property name="mail.smtp.host" value="smtp.gmail.com"/>
		<property name="mail.smtp.socketFactory.class" value="javax.net.ssl.SSLSocketFactory"/>
		<property name="mail.smtp.socketFactory.fallback" value="false"/>
		<property name="mail.smtp.auth" value="true"/>        
        <!-- The mail server port -->
        <property name="mail.smtp.port" value="465"/>        
        <!-- Change to the address mail will be from  -->
        <property name="mail.from" value="[email protected]"/>
        <!-- Enable debugging output from the javamail classes -->
        <property name="mail.debug" value="false"/>
      </configuration>
    </attribute>
    <depends>jboss:service=Naming</depends>
  </mbean>
</server>

만약 메일 발송이 성공하지 못한다면, "mail.debug"의 값을true 디버깅으로 바꿀 수 있습니다.
2.%JBOSS_HOME%\server\default\deploy\jms 아래 jbossmq-destinations-service.xml, 이 파일은 Topic 및Queue 구성에 사용
<mbean code="org.jboss.mq.server.jmx.Topic"
	 name="jboss.mq.destination:service=Topic,name=testTopic">
    <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
    <depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
    <attribute name="SecurityConf">
      <security>
        <role name="guest" read="true" write="true"/>
        <role name="publisher" read="true" write="true" create="false"/>
        <role name="durpublisher" read="true" write="true" create="true"/>
      </security>
    </attribute>
  </mbean>

   <mbean code="org.jboss.mq.server.jmx.Queue"
	 name="jboss.mq.destination:service=Queue,name=fmQueue">
    <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
    <depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
    <attribute name="MessageCounterHistoryDayLimit">-1</attribute>
    <attribute name="SecurityConf">
      <security>
        <role name="guest" read="true" write="true"/>
        <role name="publisher" read="true" write="true" create="false"/>
        <role name="noacc" read="false" write="false" create="false"/>
      </security>
    </attribute>
  </mbean>

JBoss를 실행하면 콘솔에서 직접 구성된 Topic 또는 Queue의 이름을 볼 수 있습니다.
 
수신자 메일 주소, 테마, 내용, 첨부 파일 주소 등 메일을 보내는 데 필요한 매개 변수를 봉인하는 실체를 정의합니다.
import java.io.Serializable;
import java.util.Date;

public class EmailEntity implements Serializable {

    private static final long serialVersionUID = 3436776941158302904L;
    private String from; 
    private String to;  
    private String subject;   
    private String content;
    private String multiPartFile;
    private Date sendDate;
    
    public EmailEntity() {
        
    }
    public EmailEntity(String to, String subject, String content, String multiPartFile) {
        this.to = to;
        this.subject = subject;
        this.content = content;
        this.multiPartFile = multiPartFile;
    }
    public String getFrom() {
        return from;
    }
    public void setFrom(String from) {
        this.from = from;
    }
    public String getTo() {
        return to;
    }
    public void setTo(String to) {
        this.to = to;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public String getMultiPartFile() {
        return multiPartFile;
    }
    public void setMultiPartFile(String multiPartFile) {
        this.multiPartFile = multiPartFile;
    }
    public Date getSendDate() {
        return sendDate;
    }
    public void setSendDate(Date sendDate) {
        this.sendDate = sendDate;
    }
}

 
 
일반적인 Java 클래스인 Message Producer를 작성합니다. 이 클래스에서 JMS의 API를 사용합니다.
import java.util.Properties;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.log4j.Logger;

public class MsgProducerService {
    
    private static Logger logger = Logger.getLogger(MsgProducerService.class);
    
    private static InitialContext context;
    private static Queue queue;
    private static QueueConnectionFactory connectionFactory;
    
    private static InitialContext getInitialContext() throws NamingException {
        if(context == null) {
            Properties env = new Properties();
            env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
            env.setProperty(Context.PROVIDER_URL, "localhost");
            context = new InitialContext(env);
        }
        return context;
    }
    
    static {
           try {
            connectionFactory = (QueueConnectionFactory) getInitialContext().lookup("ConnectionFactory");
            queue = (Queue) getInitialContext().lookup("queue/fmQueue");
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
    
    public static void sendMail(EmailEntity emailEntity) {
        
        QueueConnection connection = null;
        QueueSession session = null;
        MessageProducer producer;
        
        try {
            connection = connectionFactory.createQueueConnection();
            session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
            producer = session.createProducer(queue);
            ObjectMessage msg = session.createObjectMessage();
            msg.setObject(emailEntity);
            producer.send(msg);
        } catch (JMSException e) {
            logger.error("Send email error:"+e);
            e.printStackTrace();
        } finally {
            try {
                if(session != null)
                    session.close();
                if(connection != null)
                    connection.close();
            } catch (JMSException e) {
                    e.printStackTrace();
            }
        }
    }
}

위의 코드에서 ObjectMessage는 당신의 메시지 유형에 따라 결정됩니다. StreamMessage가 있습니다. 주체에 자바의 기본 값 흐름을 포함하는 메시지입니다.채우기와 읽기는 순서대로 진행됩니다.MapMessage: 바디에 이름 - 값 쌍의 메시지가 포함됩니다.(항목 순서가 정의되지 않음) TextMessage: 바디에 Java 문자열이 포함된 메시지 (예: XML 메시지) ObjectMessage: 바디에 정렬된 Java 객체가 포함된 메시지입니다.BytesMessage: 연속적인 바이트 흐름을 포함하는 바디 메시지입니다.
 
다음은 메시지 수신자를 정의합니다. 이 종류는 MessageListener 인터페이스를 실현하고 자동으로 메시지를 감청하는 상태입니다. 메시지가 도착할 때 onMessage 방법을 터치합니다.
import java.io.File;
import java.util.Date;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.naming.Context;
import javax.naming.InitialContext;

// destination , Queue, fmQueue
@MessageDriven(activationConfig ={
        @ActivationConfigProperty(propertyName = "destinationType",
                propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "destination",
                propertyValue = "queue/fmQueue")
})
public class EmailBean implements MessageListener {

    @Override
    public void onMessage(javax.jms.Message msg) {
        try {
            if(msg != null && msg instanceof ObjectMessage) {
                ObjectMessage objMsg = (ObjectMessage)msg;
                EmailEntity emailEntity = (EmailEntity) objMsg.getObject();
                sendMail(emailEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    
    // 
    private void sendMail(EmailEntity emailEntity) throws Exception {
        if(emailEntity == null)
            return;
        
        Context context = new InitialContext();
        Session session = (Session) context.lookup("java:/Mail");
        MimeMessage msg = new MimeMessage(session);
        msg.setFrom();
        
        if(emailEntity.getTo() != null && emailEntity.getTo().trim().length() > 0) {
            String[] toArr = emailEntity.getTo().split(",");
            if(toArr.length > 0) {
                InternetAddress[] addressArr = new InternetAddress[toArr.length];
                for(int i = 0; i < toArr.length; i++) {
                    addressArr[i] = new InternetAddress(toArr[i]);
                }
                msg.addRecipients(Message.RecipientType.TO, addressArr);
            }
        }
        if(emailEntity.getSubject() != null)
            msg.setSubject(emailEntity.getSubject(), "UTF-8");
        
        if(emailEntity.getMultiPartFile() != null) {
            File file = new File(emailEntity.getMultiPartFile());
            if(file.exists()) {
		// 
                Multipart multipart = new MimeMultipart();
                MimeBodyPart bodyPart = new MimeBodyPart();
                FileDataSource fds = new FileDataSource(emailEntity.getMultiPartFile());
                bodyPart.setDataHandler(new DataHandler(fds));
                bodyPart.setFileName(fds.getName());
                multipart.addBodyPart(bodyPart);
                
                if(emailEntity.getContent() != null) {
                    MimeBodyPart bodyPartText = new MimeBodyPart();
                    bodyPartText.setText(emailEntity.getContent(), "UTF-8");
                    multipart.addBodyPart(bodyPartText);
                }
                msg.setContent(multipart);
            } else
                return;
        }
        
        msg.setSentDate(new Date());
        msg.saveChanges();
        Transport.send(msg, msg.getRecipients(Message.RecipientType.TO));
    }
}

이렇게 하면 우편물의 비동기적인 발송을 실현할 수 있다.

좋은 웹페이지 즐겨찾기