Enviando e-mail pelo Spring!

4 respostas
Pilantra

Olá pessoal.

Agora que eu consegui entender a filosofia do Spring hehe. Estou tentando fazer uma classe para enviar e-mail. Eu fiz as seguintes classes:

SpringMail.java
public class SpringMail {

	private JavaMailSender mailSender;
	
	public void setMailSender(JavaMailSender mailSender) {
		this.mailSender = mailSender;
	}
	
	public void send() {
		System.out.println("coisando...");
		
		SimpleMailMessage msg = new SimpleMailMessage();

		msg.setFrom("TestCase <[email removido]>");
		msg.setText("texticulo de teste");

		msg.setTo("[email removido]");
		msg.setSubject("titulo do email");
		msg.setSentDate(new Date());
		
		try {
			mailSender.send(msg);
		} catch (MailException ex) {
			ex.printStackTrace();
		}
	}

}
applicationContext-javamail.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
   "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

	<bean id="mailSender" autowire="byName"
		class="org.springframework.mail.javamail.JavaMailSenderImpl">
		<property name="host">
			<value>mail.meuhost.com.br</value>
		</property>
	</bean>

	<bean id="springMail" autowire="byName"
		class="br.org.articulus.server.SpringMail">

		<property name="mailSender">
			<ref bean="mailSender" />
		</property>
		
	</bean>

</beans>

E fiz um testcase bem básico só pra testar o método:

public class SpringMailTest extends AbstractSpringContextTests {

	private SpringMail springMail;
	
	public void setSpringMail(SpringMail springMail) {
		this.springMail = springMail;
	}
	
	protected void setUp() throws Exception {
		loadContext(new String[] {"applicationContext-javamail.xml"});
	}
	
	public void testSend() {
		springMail.send();
	}
	
	protected ConfigurableApplicationContext loadContext(Object arg0)
			throws Exception {
		return new ClassPathXmlApplicationContext((String[])arg0);
	}

}

Quando eu rodo o testCase ele retorna o seguinte erro:

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.408 sec <<< FAILURE! testSend(br.org.articulus.server.SpringMailTest) Time elapsed: 1.249 sec <<< ERROR! java.lang.NullPointerException at br.org.articulus.server.SpringMailTest.testSend(SpringMailTest.java:20) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at junit.framework.TestCase.runTest(TestCase.java:168) at junit.framework.TestCase.runBare(TestCase.java:134) at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:76) at junit.framework.TestResult$1.protect(TestResult.java:110) at junit.framework.TestResult.runProtected(TestResult.java:128) at junit.framework.TestResult.run(TestResult.java:113) at junit.framework.TestCase.run(TestCase.java:124) at junit.framework.TestSuite.runTest(TestSuite.java:232) at junit.framework.TestSuite.run(TestSuite.java:227) at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:81) at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62) at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140) at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127) at org.apache.maven.surefire.Surefire.run(Surefire.java:177) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345) at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)

Quando eu inicio o testCase, ele carrega os beans, eu acho que ele não está injetando porque nem o método send() ele executa. Vejam a saída do Spring:

Running br.org.articulus.server.SpringMailTest 07/07/2008 11:01:57 org.springframework.context.support.AbstractApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@197d257: display name [org.springframework.context.support.ClassPathXmlApplicationContext@197d257]; startup date [Mon Jul 07 11:01:57 BRT 2008]; root of context hierarchy 07/07/2008 11:01:58 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [applicationContext-javamail.xml] 07/07/2008 11:01:58 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory INFO: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@197d257]: org.springframework.beans.factory.support.DefaultListableBeanFactory@1893efe 07/07/2008 11:01:58 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1893efe: defining beans [mailSender,springMail]; root of factory hierarchy

Alguém me ajuda a resolver esse mistério?

4 Respostas

L

Mistério nenhum! SpringMailTest NÃO é bean do Spring, e este não tem obrigação nenhuma de injetar alguma coisa. A primeira classe que obtém o bean, deve sempre buscá-lo à mão. Assim:

public class SpringMailTest extends AbstractSpringContextTests {

	private ConfigurableApplicationContext ctx;
	
	public SpringMail getSpringMail() {
		return (SpringMail) ctx.getBean("springMail");
	}
	
	protected void setUp() throws Exception {
		ctx = loadContext(new String[] {"applicationContext-javamail.xml"});
	}
	
	public void testSend() {
		getSpringMail().send();
	}
	
	protected ConfigurableApplicationContext loadContext(Object arg0)
			throws Exception {
		return new ClassPathXmlApplicationContext((String[])arg0);
	}
}

Repare, nem compilei pra ver se funciona.

Só achei estranho a ausência de interface para a classe SpringMail, porque você sempre injeta uma classe para atributo interface, para ganhar flexibilidade. Se não fizer isso, não há justificativa para usar Spring, bastaria dar new direto.

Pilantra

Humm entendi, se eu criar um bean do SpringMailTest ele injeta automaticamente??

Usando o getBean funcionou!!!

Valeu!!

L

Pilantra:
Humm entendi, se eu criar um bean do SpringMailTest ele injeta automaticamente??

Usando o getBean funcionou!!!

Valeu!!

Sim, mas lembre-se. O Spring apenas faz a injeção, não sai executando sozinho o seu programa. Sempre você tem que buscar o bean “raiz” à mão. Ou seja, se SpringMailTest for um bean, você terá que buscar no Context e executá-lo.

O Spring, pra facilitar, tem um mooonte de wrappers para outros frameworks, para que a busca do primeiro bean seja mais fácil. Mas isso é bastante extenso, terá que olhar a documentação.

Pilantra

Humm entendi!!! Valeu cara, eu estou criando uma interface para ficar mais bonito a implementação e já removi a minha classe que usava o JavaMail hehe.

Valeu…

Criado 7 de julho de 2008
Ultima resposta 7 de jul. de 2008
Respostas 4
Participantes 2