PDA

View Full Version : MailTarget help



kantorn
Sep 2nd, 2008, 08:24 AM
Hi

I just cannot get MailTarget to work.

Config:


<integration:message-bus auto-startup="true"/>

<integration:channel id="outboundMailChannel" />

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderIm pl">
<property name="host"><value>smtp.ki.se</value></property>
<property name="port"><value>25</value></property>
</bean>

<integration:jms-gateway
id="mailJmsGateway"
request-channel="outboundMailChannel"
reply-channel="outboundMailChannel"
connection-factory="jmsFactory"
destination="outboundMailQueue"
expect-reply="false"
/>

<integration:mail-target
id="sendMailTarget"
mail-sender="mailSender"
/>

<integration:channel-adapter target="sendMailTarget" channel="outboundMailChannel">
<integration:poller period="3000" />
</integration:channel-adapter>



Message constructed as:


/**
* Transform a ELSA MailMessage into a
* Spring integration mail message
* @param msg
* @return
*/
public static final Message toIntegrationMessage(MailMessage msg){
Message out = MessageBuilder
.fromPayload(msg.getMessage())
.setHeader(MailHeaders.TO, msg.recipientsAsArray())
.setHeader(MailHeaders.FROM, msg.getFrom())
.setHeader(MailHeaders.SUBJECT, msg.getSubject())
.setHeader(MailHeaders.CC, msg.ccRecipientsAsArray())
.setHeader(MailHeaders.BCC, msg.bccRecipientsAsArray())
.setHeader(MailHeaders.REPLY_TO, msg.getFrom())
.build();

return out;
}


Exception:


[2008-09-02 12:25:11,868] WARN org.springframework.integration.adapter.mail.Defau ltMailHeaderGenerator no 'SUBJECT' property available for mail message
[2008-09-02 12:25:11,868] WARN org.springframework.integration.adapter.mail.Defau ltMailHeaderGenerator no 'SUBJECT' property available for mail message
[2008-09-02 12:25:11,899] DEBUG org.springframework.integration.channel.QueueChann el postSend (sent=true) on channel 'outboundMailChannel', message: [Payload=[Payload=Hej hej! Du är född, icke skapad.][Headers={CC=[], internal.header.id=0cc42c85-fb9d-44d8-9a2e-d46ecac2db2a, TO=[bengt-erik.froberg@ki.se], internal.header.timestamp=1220350404931, REPLY_TO=elsa@ki.se, FROM=elsa@ki.se}]][Headers={internal.header.id=9d11eb61-3204-45be-ac9e-5b99638384fc, internal.header.timestamp=1220351111868, spring.integration.transport.jms.JMSRedelivered=fa lse}]
[2008-09-02 12:25:11,899] DEBUG org.springframework.integration.channel.QueueChann el postSend (sent=true) on channel 'outboundMailChannel', message: [Payload=[Payload=Hej hej! Du är född, icke skapad.][Headers={CC=[], internal.header.id=0cc42c85-fb9d-44d8-9a2e-d46ecac2db2a, TO=[bengt-erik.froberg@ki.se], internal.header.timestamp=1220350404931, REPLY_TO=elsa@ki.se, FROM=elsa@ki.se}]][Headers={internal.header.id=9d11eb61-3204-45be-ac9e-5b99638384fc, internal.header.timestamp=1220351111868, spring.integration.transport.jms.JMSRedelivered=fa lse}]
[2008-09-02 12:25:11,993] WARN org.springframework.integration.adapter.mail.Defau ltMailHeaderGenerator no 'TO' property available for mail message
[2008-09-02 12:25:11,993] WARN org.springframework.integration.adapter.mail.Defau ltMailHeaderGenerator no 'TO' property available for mail message
[2008-09-02 12:25:12,118] WARN org.springframework.integration.adapter.mail.Defau ltMailHeaderGenerator no 'FROM' property available for mail message
[2008-09-02 12:25:12,118] WARN org.springframework.integration.adapter.mail.Defau ltMailHeaderGenerator no 'FROM' property available for mail message
[2008-09-02 12:25:12,446] WARN org.springframework.integration.endpoint.OutboundC hannelAdapter exception occurred in endpoint 'org.springframework.integration.endpoint.Outbound ChannelAdapter#0'
org.springframework.integration.message.MessageHan dlingException: failure occurred in endpoint 'org.springframework.integration.endpoint.Outbound ChannelAdapter#0'
at org.springframework.integration.endpoint.AbstractE ndpoint.send(AbstractEndpoint.java:119)
at org.springframework.integration.message.MessageExc hangeTemplate.doSend(MessageExchangeTemplate.java: 200)
at org.springframework.integration.message.MessageExc hangeTemplate.send(MessageExchangeTemplate.java:15 5)
at org.springframework.integration.dispatcher.Abstrac tDispatcher.sendMessageToTarget(AbstractDispatcher .java:75)
at org.springframework.integration.dispatcher.SimpleD ispatcher.send(SimpleDispatcher.java:48)
at org.springframework.integration.message.MessageExc hangeTemplate.doSend(MessageExchangeTemplate.java: 200)
at org.springframework.integration.message.MessageExc hangeTemplate.doReceiveAndForward(MessageExchangeT emplate.java:235)
at org.springframework.integration.message.MessageExc hangeTemplate.receiveAndForward(MessageExchangeTem plate.java:191)
at org.springframework.integration.dispatcher.Polling Dispatcher.run(PollingDispatcher.java:127)
at org.springframework.integration.scheduling.spi.Pro viderTaskScheduler$TaskRunner.run(ProviderTaskSche duler.java:221)
at java.util.concurrent.Executors$RunnableAdapter.cal l(Executors.java:417)
at java.util.concurrent.FutureTask$Sync.innerRun(Futu reTask.java:269)
at java.util.concurrent.FutureTask.run(FutureTask.jav a:123)
at java.util.concurrent.ScheduledThreadPoolExecutor$S cheduledFutureTask.access$301(ScheduledThreadPoolE xecutor.java:65)
at java.util.concurrent.ScheduledThreadPoolExecutor$S cheduledFutureTask.run(ScheduledThreadPoolExecutor .java:168)
at java.util.concurrent.ThreadPoolExecutor$Worker.run Task(ThreadPoolExecutor.java:650)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:675)
at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.NullPointerException
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTr ansport.java:557)
at org.springframework.mail.javamail.JavaMailSenderIm pl.doSend(JavaMailSenderImpl.java:403)
at org.springframework.mail.javamail.JavaMailSenderIm pl.send(JavaMailSenderImpl.java:308)
at org.springframework.mail.javamail.JavaMailSenderIm pl.send(JavaMailSenderImpl.java:297)
at org.springframework.integration.adapter.mail.MailT arget.sendMailMessage(MailTarget.java:106)
at org.springframework.integration.adapter.mail.MailT arget.send(MailTarget.java:89)
at org.springframework.integration.message.MessageExc hangeTemplate.doSend(MessageExchangeTemplate.java: 200)
at org.springframework.integration.message.MessageExc hangeTemplate.send(MessageExchangeTemplate.java:15 5)
at org.springframework.integration.endpoint.OutboundC hannelAdapter.sendInternal(OutboundChannelAdapter. java:32)
at org.springframework.integration.endpoint.AbstractE ndpoint.send(AbstractEndpoint.java:111)
... 17 more


Anybody see what I'm douing wrong and where tje NPE m ight occur...

kantorn
Sep 4th, 2008, 10:03 AM
Seems like my carefully produced message is wrapped up an extra time..



[2008-09-04 16:40:52,654] DEBUG org.springframework.integration.channel.QueueChann el postReceive on channel 'outboundMailChannel', message:
[Payload=
[Payload=
Hej hej! Du är född, icke skapad.
]
[Headers=
{spring.integration.transport.mail.REPLY_TO=sdmbio bank@ki.se,
spring.integration.transport.mail.FROM=sdmbiobank@ ki.se,
internal.header.id=5725459f-8a51-4111-aa3e-8adc41774c14,
spring.integration.transport.mail.TO=[Ljava.lang.String;@1126d91,
spring.integration.transport.mail.CC=[Ljava.lang.String;@d767dc,
internal.header.timestamp=1220539249225,
spring.integration.transport.mail.SUBJECT=Du är skapad!!, '
spring.integration.transport.mail.BCC=[Ljava.lang.String;@1e3d24a}
]
]
[Headers=
{internal.header.id=fb48a6ee-d107-40b4-8908-4070399bcc6e,
internal.header.timestamp=1220539249225,
spring.integration.transport.jms.JMSRedelivered=fa lse}
]

Mark Fisher
Sep 4th, 2008, 10:11 AM
What version are you currently using?

kantorn
Sep 4th, 2008, 11:40 AM
Hi

Spring Integration 1.0.0.M6
Spring 2.5.4

Thanks for answering, I'm stuck on how this is supposed to work.

kantorn
Sep 5th, 2008, 09:16 AM
Maybe someone could give me a hint:
What should I send into the MailTarget?
Is it a GenericMessage with the payload as a String and the rest
defined as elements of the Headers map?

Why does it get wrapped up twice?

Mark Fisher
Sep 5th, 2008, 09:23 AM
What is the actual payload object that is a result of this msg.getMessage() call?:


public static final Message toIntegrationMessage(MailMessage msg){
Message out = MessageBuilder
.fromPayload(msg.getMessage() ...

kantorn
Sep 9th, 2008, 11:12 AM
Hi



public class MailMessage implements Serializable{

/**
*
*/
private static final long serialVersionUID = -8698857545693120110L;

private static final String NL = System.getProperty("line.separator");

private List recipients;
private List cc_recipient;
private List bcc_recipient;
private String from = "";
private String subject = "";
private StringBuilder message;

public MailMessage() {
super();
this.recipients = new ArrayList();
this.cc_recipient = new ArrayList();
this.bcc_recipient = new ArrayList();
this.message = new StringBuilder("");
}

(getter & setters)

public StringBuilder getMessage() {
return message;
}


You mean the fact that this is not a String could cause this? Trying it out immediately!

kantorn
Sep 9th, 2008, 11:41 AM
Sorry, no luck, still wrapped up...

Code in flow handler (MailMessage is custom)



MailMessage notificationMessage(UserFlowFormBean command) {
MailMessage msg = new MailMessage();
msg.setFrom("sdmbiobank@ki.se");
msg.addRecipient(command.getUser().getEmail());
msg.appendToMsg("Hej hej! Du är född, icke skapad.");
msg.setSubject("Du är skapad!!");
LOG.debug("Command: " + command);
return msg;
}

public void notifyUser(UserFlowFormBean command) {
if(command.isNotifyOnCreation()) {
if(LOG.isDebugEnabled())
LOG.debug("Sending notification");
this.sender.sendMail(notificationMessage(command)) ;
} else {
if(LOG.isDebugEnabled())
LOG.debug("Notification not enabled");
}
}




And finally the mail sending service method



public void sendMail(final MailMessage msg) throws JmsException {
if(LOG.isDebugEnabled())
LOG.debug("Sending mail message " + msg);
this.jmsTemplate.send(destination, new MessageCreator() {
public javax.jms.Message createMessage(Session s) throws JMSException {
javax.jms.Message m = null;
try {
m = s.createObjectMessage((GenericMessage)MessageTranf ormer.toIntegrationMessage(msg));
} catch (JmsException e) {
LOG.error("Mail sender threw Exception.", e);
}
return m;
}
});
if(LOG.isDebugEnabled())
LOG.debug("Message sent.");
}

kantorn
Sep 18th, 2008, 03:22 AM
OK, ditching MailTarget. Have no time getting it to work.
Thanks anyway all you that answered.

Mark Fisher
Sep 18th, 2008, 06:33 AM
The MailTarget itself is actually very simple, and it looks like your MailMessage object is providing everything that is necessary. The target is expecting a Message whose payload is a String, byte array, or some other Object in which case it calls toString(), and the headers of that Message should provide TO, CC, etc. However, the actual issue here is related to the creation of a Spring Integration Message on the "client" side prior to sending it over JMS.

After looking at the additional excerpts you have provided here since the initial question was raised, I see that there is more involved than just a Message being sent to the MailTarget (hence the confusion over the initial question). It looks like you are creating the Spring Integration Message and wrapping it yourself in a JMS Message before sending it to the queue on which the JmsGateway is listening? If I do understand what's happening now, there are a few other ways to handle this (and #1 below does qualify as a bug):

1. We should modify the JMS inbound mapping for the JmsGateway so that it recognizes the received object is already a Spring Integration Message and does not try to create a new one as a wrapper (I have raised this in JIRA: http://jira.springframework.org/browse/INT-376)

2. The polling version of the JMS channel-adapter does already recognize that a received payload is a Spring Integration Message. Obviously, the message-driven gateway is probably the better option, but perhaps this would suffice until the above issue is resolved.

3. You could simply pass your custom MailMessage object as the JMS Message's payload, and then supply a custom messageConverter and/or MessageHeaderMapper for the JmsGateway so that the Spring Integration Message creation occurs on the receiving side only.

4. You could add a Message transformer to the pipeline (namespace support is still in progress, but the class is TransformerEndpoint). This approach would be similar to (but probably simpler than) option #3.

Also, this does provide another example for what we should handle after resolving this issue: http://jira.springframework.org/browse/INT-240. In general, it should not be necessary to create the Spring Integration Message prior to sending as a JMS Message. Instead, you should be able to send just the mail message text as the payload with the Mail-related headers passed along via JMS Message header properties. Currently, the JMS properties are passed along but a USER_DEFINED_PREFIX is added to them, and perhaps that is not necessary (would not be recognized by the MailTarget without some transformation taking place).

In any case, if you opt for #1 above, the issue should be resolved very soon.

Regards,
Mark

kantorn
Sep 18th, 2008, 11:14 AM
Thanks for your very informative answer. I was not aware that the object passed to JmsGateway doesn't have to be a Spring Integration Message. I will look into the different options you gave me.
Your'e all doing a fantastic job with the Spring portfolio, I will do my humble best to spread the gospel at work. ;)