I am attempting to use a #Service class in my messaging application, however the class is not instantiated via #Autowire when I try from a generic class. It is only instantiated when I use the Controller.
Here is my controller:
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import hello.Application;
#Controller
public class HelloController {
#Autowired
private MessageSender sender;
#RequestMapping(value="/", method=RequestMethod.GET)
public String index() {
return "index";
}
#MessageMapping("/hello")
#SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
System.out.println("Sending message...");
beginRoute(message.getName());
sender.greet("thunder");
return new Greeting("Hello, " + message.getName() + "!");
}
public void beginRoute(String message) {
Application.startBody(message);
}
}
The above call to sender.greet is successful.
Here is the other class I attempt to use the service in:
package com.routing.integration;
import hello.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;
#Component
public class modifier {
#Autowired
private MessageSender sender;
public boolean adder(String words) throws Exception {
sender.greet(words);
}
}
When I attempt to call sender.greet as above, I get a NullPointerException and when debugging, I find that sender is null at the time of the call to sender.greet. Is the service class not instantiating in modifier?
Finally, here is the MessageSender service class:
#Service
public class MessageSender {
#Autowired
private SimpMessagingTemplate template;
#RequestMapping(value="/hello", method=RequestMethod.POST)
public void greet(String greeting) {
Greeting text = new Greeting("Goodbye, " + greeting + "!");
this.template.convertAndSend("/topic/greetings", text);
}
}
How can I ensure that #Autowire instantiates the MessageSender in every class?
EDIT
Here is where the call to modifier is made. It is made from a camel route:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:core="http://activemq.apache.org/schema/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://camel.apache.org/schema/osgi http://camel.apache.org/schema/osgi/camel-osgi.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core">
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="activemq:queue:testQSource"/>
<choice>
<when>
<method ref="securityBean"/>
<log message="Routing message from testQSource to testQDestination queue with data ${body}"/>
<to uri="activemq:queue:testQDestination"/>
<to uri="activationBean"/>
<to uri="accountVerificationBean"/>
<to uri="billingCheckingBean"/>
<to uri="deviceConnectorBean"/>
<to uri="deviceActivatorBean"/>
<log message="Account activated: ${body}"/>
</when>
<otherwise>
<log message="message went to stomp: ${body}"/>
</otherwise>
</choice>
</route>
</camelContext>
<camel:camelContext id="camel-client">
<camel:template id="camelTemplate" />
</camel:camelContext>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
<bean id="browserBean" class="hello.HelloController"/>
<bean id="securityBean" class="com.routing.integration.modifier"/>
<bean id="activationBean" class="com.routing.integration.ActionApp"/>
<bean id="accountVerificationBean" class="com.routing.integration.AccountVerifier"/>
<bean id="billingCheckingBean" class="com.routing.integration.BillingChecker"/>
<bean id="deviceConnectorBean" class="com.routing.integration.DeviceConnector"/>
<bean id="deviceActivatorBean" class="com.routing.integration.DeviceActivator"/>
</beans>
Here is the stacktrace:
Stacktrace
--------------------------------------------------------------------------------------- ------------------------------------------------
java.lang.NullPointerException
at com.routing.integration.modifier.adder(modifier.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:407)
at org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:278)
at org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:251)
at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:166)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:105)
at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:67)
at org.apache.camel.language.bean.BeanExpression$InvokeProcessor.process(BeanExpression.java:1 89)
at org.apache.camel.language.bean.BeanExpression.evaluate(BeanExpression.java:123)
at org.apache.camel.language.bean.BeanExpression.matches(BeanExpression.java:137)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:90)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java: 72)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:398)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:105)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:87)
at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.ja va:103)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(Abstract MessageListenerContainer.java:562)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMe ssageListenerContainer.java:500)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(Abstrac tMessageListenerContainer.java:468)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecut e(AbstractPollingMessageListenerContainer.java:325)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute( AbstractPollingMessageListenerContainer.java:263)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke r.invokeListener(DefaultMessageListenerContainer.java:1102)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke r.executeOngoingLoop(DefaultMessageListenerContainer.java:1094)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke r.run(DefaultMessageListenerContainer.java:991)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
WARN : org.apache.camel.component.jms.EndpointMessageListener - Execution of JMS message listener failed. Caused by: [org.apache.camel.RuntimeCamelException - java.lang.NullPointerException]
org.apache.camel.RuntimeCamelException: java.lang.NullPointerException
at org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException(ObjectHelper.java:1363)
at org.apache.camel.component.jms.EndpointMessageListener$EndpointMessageListenerAsyncCallback .done(EndpointMessageListener.java:186)
at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.ja va:107)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(Abstract MessageListenerContainer.java:562)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMe ssageListenerContainer.java:500)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(Abstrac tMessageListenerContainer.java:468)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecut e(AbstractPollingMessageListenerContainer.java:325)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute( AbstractPollingMessageListenerContainer.java:263)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke r.invokeListener(DefaultMessageListenerContainer.java:1102)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke r.executeOngoingLoop(DefaultMessageListenerContainer.java:1094)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke r.run(DefaultMessageListenerContainer.java:991)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at com.routing.integration.modifier.adder(modifier.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:407)
at org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:278)
at org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:251)
at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:166)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:105)
at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:67)
at org.apache.camel.language.bean.BeanExpression$InvokeProcessor.process(BeanExpression.java:1 89)
at org.apache.camel.language.bean.BeanExpression.evaluate(BeanExpression.java:123)
at org.apache.camel.language.bean.BeanExpression.matches(BeanExpression.java:137)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:90)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java: 72)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:398)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:105)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:87)
at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.ja va:103)
... 11 more
EDIT 2
Here is my main class that calls ComponentScan:
package hello;
import org.apache.camel.ProducerTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackages = {"hello", "com.routing.integration"})
public class Application {
static ApplicationContext context = null;
static ProducerTemplate camelTemplate = null;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
System.out.println("----------------------\nSpringBootComplete\n----------------------");
startBody("startup");
}
public static void startBody(String message) {
if (context == null) {
context = new ClassPathXmlApplicationContext("camelspring.xml");
camelTemplate = context.getBean("camelTemplate", ProducerTemplate.class);
}
if (message != "startup"){
camelTemplate.sendBody("activemq:queue:testQSource", message);
}
}
}
Your Application class should look like this:
#Configuration
#ComponentScan(basePackages = {"hello", "com.routing.integration"})
#EnableAutoConfiguration
#ImportResource("classpath:camel.xml")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Where camel.xml is the xml configuration file that contains your camel definitions.
If you need any of the beans defined in the xml configuration, like camelTemplate in your xml, you can get a reference of it like this, for example:
package hello;
import javax.annotation.Resource;
import org.apache.camel.ProducerTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MyController {
#Resource(name="camelTemplate")
private ProducerTemplate template;
#RequestMapping("/")
String home() {
System.out.println(template);
return "Hello World!";
}
}
As I said in the comments, don't create an app context manually. Register the beans you want with #Component, #Service, #Configuration and #Bean etc. If you need xml configuration that is difficult to reproduce in Java code, use #ImportResource.
In the xml config file you have, you can replace browserBean bean with a #Controller annotation placed on the hello.HelloController class.
Your activemq bean could translate to something like this in Java Config:
#Configuration
public class Config {
#Bean
public ActiveMQComponent activemq() {
ActiveMQComponent comp = new ActiveMQComponent();
comp.setBrokerUrl("tcp://localhost:61616");
return comp;
}
}
Related
I am trying to parameterize cron expression and reading it from properties file. During this process I get following exception "Error creating bean with name 'springScheduleCronExample': Initialization of bean failed; nested exception is java.lang.IllegalStateException: Encountered invalid #Scheduled method 'cronJob': Cron expression must consist of 6 fields (found 1 in "${cron.expression}")".
Then I found following post
Using that I cron expression is being read, only if I have
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
SpringScheduleCronExample.class);
define in my main method. The issue that I am having is, I want to run this on server without main method, can anyone please help me with this.
Here is my applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<task:annotation-driven />
<util:properties id="applicationProps" location="application.properties" />
<context:property-placeholder properties-ref="applicationProps" />
<bean class="com.hemal.spring.SpringScheduleCronExample" />
</beans>
My SpringScheduleCronExample.java looks like this
package com.hemal.spring;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
#Configuration
#EnableScheduling
#PropertySource("classpath:application.properties")
public class SpringScheduleCronExample {
private AtomicInteger counter = new AtomicInteger(0);
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Scheduled(cron = "${cron.expression}")
public void cronJob() {
int jobId = counter.incrementAndGet();
System.out.println("Job # cron " + new Date() + ", jobId: " + jobId);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
SpringScheduleCronExample.class);
try {
Thread.sleep(24000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
context.close();
}
}
}
My application Properties has
cron.expression=*/5 * * * * ?
Here is how I got it to work
Application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<context:property-placeholder properties-ref="applicationProps" />
<context:annotation-config/>
<context:component-scan base-package="com.hemal.spring" />
<task:annotation-driven />
</beans>
MyApplicationConfig.java
package com.hemal.spring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.EnableScheduling;
#Configuration
#EnableScheduling
#ComponentScan(basePackages = {"com.hemal.spring"})
#PropertySource("classpath:application.properties")
public class MyApplicationConfig {
#Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer();
properties.setLocation(new ClassPathResource( "application.properties" ));
properties.setIgnoreResourceNotFound(false);
return properties;
}
}
MyApplicationContext.java
package com.hemal.spring;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
public class MyApplicationContext implements WebApplicationInitializer{
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(MyApplicationConfig.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
}
}
My scheduler class
package com.hemal.spring;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
public class SpringScheduleCronExample {
private AtomicInteger counter = new AtomicInteger(0);
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Scheduled(cron = "${cron.expression}")
public void cronJob() {
int jobId = counter.incrementAndGet();
System.out.println("Job # cron " + new Date() + ", jobId: " + jobId);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
SpringScheduleCronExample.class);
try {
Thread.sleep(24000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
context.close();
}
}
}
application.properties
cron.expression=0/5 * * * * ?
I have some problems converting Imap Idle XML configuration (which works well) to Java Config (which does not work).
I'm pretty new with Spring, so the problem is probably trivial.
Thanks for your help!
XML Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/mail http://www.springframework.org/schema/integration/mail/spring-integration-mail.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-mail="http://www.springframework.org/schema/integration/mail"
xmlns:util="http://www.springframework.org/schema/util">
<int:channel id="emails"/>
<util:properties id="javaMailProperties">
<prop key="mail.imap.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
<prop key="mail.imap.socketFactory.fallback">false</prop>
<prop key="mail.store.protocol">imaps</prop>
<prop key="mail.debug">true</prop>
</util:properties>
<int-mail:imap-idle-channel-adapter id="mailAdapter"
store-uri="imaps://login:pass#imap-server:993/INBOX"
java-mail-properties="javaMailProperties"
channel="emails"
should-delete-messages="false"
should-mark-messages-as-read="true">
</int-mail:imap-idle-channel-adapter>
</beans>
Java Config:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.mail.ImapIdleChannelAdapter;
import org.springframework.integration.mail.ImapMailReceiver;
import org.springframework.messaging.MessageChannel;
import java.util.Properties;
#Configuration
public class ImapConfig{
private Properties javaMailProperties() {
Properties javaMailProperties = new Properties();
javaMailProperties.setProperty("mail.imap.socketFactory.class","javax.net.ssl.SSLSocketFactory");
javaMailProperties.setProperty("mail.imap.socketFactory.fallback","false");
javaMailProperties.setProperty("mail.store.protocol","imaps");
javaMailProperties.setProperty("mail.debug","true");
return javaMailProperties;
}
#Bean
MessageChannel messageChannel() {
return new DirectChannel();
}
#Bean
ImapIdleChannelAdapter mailAdapter() {
ImapMailReceiver mailReceiver = new ImapMailReceiver("imaps://login:pass#imap-server:993/INBOX");
mailReceiver.setJavaMailProperties(javaMailProperties());
mailReceiver.setShouldDeleteMessages(false);
mailReceiver.setShouldMarkMessagesAsRead(true);
ImapIdleChannelAdapter imapIdleChannelAdapter = new ImapIdleChannelAdapter(mailReceiver);
imapIdleChannelAdapter.setOutputChannel(messageChannel());
return imapIdleChannelAdapter;
}
}
Main.java:
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
public class Main {
public static void main(String args[]) {
ApplicationContext ac = new AnnotationConfigApplicationContext(ImapConfig.class);
DirectChannel inputChannel = ac.getBean("messageChannel", DirectChannel.class);
inputChannel.subscribe(new MessageHandler() {
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println(message);
}
});
}
}
Exceptions:
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'mailAdapter'; nested exception is java.lang.IllegalArgumentException: 'taskScheduler' must not be null
Exception in thread "main" org.springframework.context.ApplicationContextException: Failed to start bean 'mailAdapter'; nested exception is java.lang.IllegalArgumentException: 'taskScheduler' must not be null
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:176)
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:51)
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:346)
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:149)
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:112)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:874)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at Main.main(Main.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.IllegalArgumentException: 'taskScheduler' must not be null
at org.springframework.util.Assert.notNull(Assert.java:115)
at org.springframework.integration.mail.ImapIdleChannelAdapter.doStart(ImapIdleChannelAdapter.java:158)
at org.springframework.integration.endpoint.AbstractEndpoint.start(AbstractEndpoint.java:94)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:173)
... 13 more
Process finished with exit code 1
You have missed #EnableIntegration on your #Configuration: http://docs.spring.io/spring-integration/docs/4.3.1.RELEASE/reference/html/overview.html#configuration-enable-integration
I'm trying to configure mail in Spring and keep getting a null pointer exception. My suspicion is that it can't find the "mailSender" bean but I could be way off. My configuration is as follows:
web.xml
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>ERROR</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<beans:bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<beans:property name="host" value="mail.company.com"/>
</beans:bean>
</beans:beans>
SendMailTest.java
package company.test;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.activation.CommandMap;
import javax.activation.MailcapCommandMap;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mock.web.MockServletContext;
import company.AppListener;
public class SendMailTest {
private static final Logger logger = AppListener.getLogger();
#Mock
private ServletContextEvent mockServletContextEvent;
private final Map<String, Object> map = new HashMap<String, Object>();
#Mock
private ServletContext mockServletContext;
#Before
public void setUp() {
System.setProperty("java.net.preferIPv4Stack" , "true");
initMocks(this);
map.clear();
when(mockServletContextEvent.getServletContext()).thenReturn(mockServletContext);
Mockito.doAnswer(new Answer<Object>() {
public Object answer(final InvocationOnMock invocation)
throws Throwable {
final String key = (String) invocation.getArguments()[0];
final Object value = invocation.getArguments()[1];
return map.put(key, value);
}
}).when(mockServletContext).setAttribute(Mockito.anyString(), Mockito.anyObject());
Mockito.doAnswer(new Answer<Object>() {
public Object answer(final InvocationOnMock invocation)
throws Throwable {
final Object value = invocation.getArguments()[0];
return map.remove(value);
}
}).when(mockServletContext).removeAttribute(Mockito.anyString());
}
#Autowired
private MailSender mailSender;
#Test
public void testSendSimpleEmaill() {
SimpleMailMessage message = new SimpleMailMessage();
String name = "John Doe";
message.setFrom("john.doe#company.com");
message.setTo("jane.doe#company2.com");
message.setSubject("Test Email from Spring");
message.setText("Will email ever work?");
try {
mailSender.send(message);
}
catch (Exception e) {
e.printStackTrace();
System.err.println(e.getMessage());
}
}
}
Stack Trace
java.lang.NullPointerException
at company.test.SendMailTest.testSendSimpleEmaill(SendMailTest.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
null
When you're running the test with JUnit, Spring isn't loaded at all, so the autowired fields aren't being set. To run spring in a test, look into the SpringJUnit4ClassRunner.
You can also create your own instance of JavaMailSenderImpl within the setUp method and assign it to mailSender
yu need to put the configurations in your test class, also you whould like to copy your context file to the root of your test class (just file resolution, when the spring runners starts needs to load your context file)..your test class should look like this...
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "applicationContext.xml" })
#WebAppConfiguration
public class FacadeTest {
private String phoneNumber = "111111115";
#Autowired
private BussinesDelegate bussinesDelegate;
#Test
public void runTest(){
this.fullTest(phoneNumber, "aaaaa");
}
public void fullTest(String phoneNumber, String answer){
try {
bmoaBussinesDelegate.processMessage("127.0.0.1", phoneNumber, "camicase" + System.currentTimeMillis());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
and dont forget to check your dependencies!
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- Testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
The cool thing about spring, its that its IOC container can probide the same behavior as a full Java EE compliant server without needing a server, and basically what the runner does is to load the context manually, the same way you could do ir in a standole app with spring ;)
I I am trying to use spring security to control authentication in my RMI client app.
I am using maven to load 3.1.3.RELEASE spring
Then in my client xml, I am seeing "authentication-provider is not allowed here" message.
This is the spring xml file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
">
<bean id="employeeService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:1234/employee-service"/>
<property name="serviceInterface" value="rmi.common.EmployeeService"/>
<property name="refreshStubOnConnectFailure"><value>true</value></property>
<property name="remoteInvocationFactory"><ref bean="remoteInvocationFactory"/></property>
</bean>
<bean id="remoteInvocationFactory" class="org.springframework.security.remoting.rmi.ContextPropagatingRemoteInvocationFactory"/>
<security:authentication-manager alias="authManager">
<security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>
<bean id="customAuthenticationProvider" class="rmi.authentication.CustomAuthenticationProvider"/>
</beans>
This is my client side code:
package rmi.client;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import rmi.common.Employee;
import rmi.common.EmployeeService;
import javax.annotation.Resource;
import java.util.Iterator;
import java.util.List;
public class EmployeeClient {
#Resource(name = "authManager")
private org.springframework.security.authentication.AuthenticationManager authenticationManager; // specific for Spring Security
private static ApplicationContext ctx;
public static void main(String[] args) {
ctx = new ClassPathXmlApplicationContext("rmi-client-context.xml");
new EmployeeClient().exec();
}
public void exec() {
EmployeeService employee = (EmployeeService) ctx.getBean("employeeService");
Authentication authenticate = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken("myuser", "mypwd"));
if (authenticate.isAuthenticated()) {
SecurityContextHolder.getContext().setAuthentication(authenticate);
}
employee.addEmployee(new Employee("Jack Su", "address1"));
employee.addEmployee(new Employee("Alice Liu", "address2"));
List<Employee> employees = employee.getEmployees();
System.out.println("Total number of employees: " + employees.size());
Iterator<Employee> it = employees.iterator();
while (it.hasNext()) {
Employee emp = (Employee) it.next();
System.out.println(" " + emp);
}
}
}
This is my testing authentication provider:
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.ArrayList;
import java.util.List;
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication argAuth) throws AuthenticationException {
List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication auth = new UsernamePasswordAuthenticationToken(argAuth.getPrincipal(),
argAuth.getCredentials(), grantedAuths);
auth.setAuthenticated(true);
return auth;
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
Not sure about your exact error, but something in your configuration might be wrong.
Your EmployeeClient is not a Spring-Managed-Bean, because you created it with new-operator, so your #Resource(name = "authManager") should not work. If you posted all your configuration authenticationManager.authenticate(..) should produce NullPointerException.
Instead of new you could do this in your Main.
EmployeeClient client = (EmployeeClient) ctx.getBean("employeeClient");
client.exec();
(and add #Service to your EmployeeClient).
I was using Mongo DB with Spring Data, everything was working fine until I decided to use Spring AOP Aspects for the logging purpose. Here is my spring configuration, Person Service and LoggingAspect Code:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:annotation-config />
<context:spring-configured />
<context:component-scan base-package="com.vaap" />
<mongo:mongo host="127.0.0.1" port="27017" />
<mongo:db-factory dbname="rakeshdb" mongo-ref="mongo"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
<bean id="personService" class="com.vaap.PersonService"></bean>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean id="loggingAspect" class="com.vaap.aop.LoggingAspect" />
</beans>
package com.vaap;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery;
public class PersonService implements IPersonService {
#Autowired
MongoTemplate mongoTemplate;
public static final String COLLECTION_NAME = "person";
public void addPerson(Person person) {
if (!mongoTemplate.collectionExists(Person.class)) {
mongoTemplate.createCollection(Person.class);
}
person.setId(UUID.randomUUID().toString());
// mongoTemplate.save(objectToSave, collectionName);
// DBObject dbObject = (DBObject) JSON.parse(jsonStr);
mongoTemplate.insert(person, COLLECTION_NAME);
}
public List<Person> listPerson() {
return mongoTemplate.findAll(Person.class, COLLECTION_NAME);
}
public String getPersonJSON() {
BasicQuery basicQuery = new BasicQuery("{'status':'Active'}");
return mongoTemplate.find(basicQuery, String.class, COLLECTION_NAME)
.toString();
}
public void deletePerson(Person person) {
mongoTemplate.remove(person, COLLECTION_NAME);
}
public void updatePerson(Person person) {
mongoTemplate.insert(person, COLLECTION_NAME);
}
}
package com.vaap.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Component;
#Component
#Configurable
#Aspect
public class LoggingAspect {
static final Logger log = LoggerFactory.getLogger(LoggingAspect.class);
#AfterThrowing(pointcut = "execution(* *.*(..))", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
log.error("An exception has been thrown in "
+ joinPoint.getSignature().getName() + "()");
log.error("Cause :" + e.getCause());
}
#Around("execution(* *.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("The method " + joinPoint.getSignature().getName()
+ "() begins with " + Arrays.toString(joinPoint.getArgs()));
try {
Object result = joinPoint.proceed();
log.info("The method " + joinPoint.getSignature().getName()
+ "() ends with " + result);
return result;
} catch (IllegalArgumentException e) {
log.error("Illegal argument "
+ Arrays.toString(joinPoint.getArgs()) + " in "
+ joinPoint.getSignature().getName() + "()");
throw e;
}
}
}
If I comment <aop:aspectj-autoproxy proxy-target-class="true"/> line everything works fine otherwise I am getting this error:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'mongoTemplate' defined in class path resource [SpringConfig.xml]:
Cannot resolve reference to bean 'mongoDbFactory' while setting constructor argument;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'mongoDbFactory': Initialization of bean failed;
nested exception is org.springframework.aop.framework.AopConfigException:
Could not generate CGLIB subclass of class [class org.springframework.data.mongodb.core.SimpleMongoDbFactory]:
Common causes of this problem include using a final class or a non-visible class;
nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments
I know, it may not be spring problem as this is standard CGI Lib behaviour but what alternatives do I have if I want to go with XML configuration and want to use both, spring data with mongodb and spring aop for logging.