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 ;)
Related
I am very new to swagger. I have created a sample JAX-RS project in which I have integrated the swagger 2.0 documentation. After a lot of unsuccessful tries, I am still not able to figure out how will I migrate my swagger 2.0 documentation to swagger 3.0. Also, what is the easiest way to host the swagger UI in my project?
So, in short, I have 2 question
1) How do I migrate this to swagger 3.0 ?
2) What is the easiest way to self-host the swagger UI in this project?
Below the sample code for my project's main files for reference.
I would really appreciate the help. Thank you so much!!!
==================== pom.xml File ====================
<!-- Swagger -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.18</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.18</version>
</dependency>
==================== web.xml File ====================
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Starbucks Web Application</display-name>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
==================== Main App File ====================
package com.starbucks.app;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Stage;
import com.google.inject.servlet.ServletModule;
import com.starbucks.cors.SimpleCorsFilter;
import com.starbucks.guice.ApiBaseModule;
import com.starbucks.request.ObjectMapperContextResolver;
import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.jvnet.hk2.guice.bridge.api.GuiceBridge;
import org.jvnet.hk2.guice.bridge.api.GuiceIntoHK2Bridge;
import javax.inject.Inject;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.HttpHeaders;
#ApplicationPath("api")
public class App extends ResourceConfig {
#Inject
public App(final ServiceLocator serviceLocator) {
// Packages to Scan for Jersey Resources
packages(true, "com.starbucks.api");
packages(true, "com.starbucks.exception.mapper");
// Jackson
register(ObjectMapperContextResolver.class);
register(JacksonFeature.class);
// HK2-Guice Bridge
Injector injector = createGuiceInjector();
initGuiceIntoHK2Bridge(serviceLocator, injector);
// Register Filters
// CORSFilter
register(SimpleCorsFilter.newBuilder()
.allowOriginDomain("localhost")
.allowCredentials()
.allowMethod(HttpMethod.GET)
.allowMethod(HttpMethod.OPTIONS)
.allowMethod(HttpMethod.POST)
.allowMethod(HttpMethod.PUT)
.allowHeader(HttpHeaders.CONTENT_TYPE)
.build());
// Jersey Event Listener
// Swagger
register(ApiListingResource.class);
register(SwaggerSerializers.class);
setUpSwagger();
//Tracing
property(ServerProperties.TRACING, "ON_DEMAND");
property(ServerProperties.TRACING_THRESHOLD, "VERBOSE");
//Jersey BeanValidation
property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
}
private void initGuiceIntoHK2Bridge(final ServiceLocator serviceLocator, final Injector injector) {
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(injector);
}
private boolean isMac() {
return "mac os x".equalsIgnoreCase(System.getProperty("os.name"));
}
private Module[] getBaseModule() {
return new Module[]{
new ServletModule(),
new ApiBaseModule()
};
}
private Injector createGuiceInjector() {
if (isMac()) {
return Guice.createInjector(getBaseModule());
} else {
return Guice.createInjector(Stage.PRODUCTION, getBaseModule());
}
}
private BeanConfig setUpSwagger() {
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.2");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/api");
beanConfig.setResourcePackage("com.starbucks.api");
beanConfig.setDescription("Provides the list of APIs for Starbucks backend");
beanConfig.setTitle("Starbucks Backend API");
beanConfig.setScan(true);
return beanConfig;
}
}
==================== Resource File ====================
package com.starbucks.api;
import com.starbucks.config.SharedConfig;
import com.starbucks.service.PingService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Api(value = "Health Check")
#Path("v1")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class PingApiResource {
private SharedConfig config;
private PingService pingService;
#Inject
public PingApiResource(final SharedConfig config, final PingService pingService) {
this.config = config;
this.pingService = pingService;
}
#GET
#Path("/ping")
#ApiOperation(value = "Ping API",
notes = "Simple Ping API for health check",
response = String.class)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "OK"),
#ApiResponse(code = 404, message = "PING NOT FOUND"),
#ApiResponse(code = 500, message = "INTERNAL SERVER ERROR")
})
public Response ping() {
String res = pingService.getPingResponse();
System.out.println(config.getList("whiteListedDomains"));
return Response.ok().entity("{\"data\":\"" + res + " from " + config.appName("appName") + "\"}").build();
}
}
I would really appreciate the help. Thank you so much!!!
I'm trying to get my test using JUnit5, but am getting a NullPointerException on the auto-wired restTemplate bean.
TestConfig:
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
#Configuration
public class TestConfig {
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
Working using JUnit4 classes:
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.apache.commons.lang3.math.NumberUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import lombok.extern.log4j.Log4j2;
#RunWith(SpringRunner.class)
#SpringBootTest
#ContextConfiguration(classes = {TestConfig.class, RestTemplateAutoConfiguration.class})
#Log4j2
public class Test {
#Value("${service.url.base}/security-marking/count")
private String countUrl;
#Autowired
private RestTemplate restTemplate;
#Test
public void testCount() throws Exception {
LOG.info(countUrl);
ResponseEntity<String> response = restTemplate.getForEntity(countUrl, String.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertTrue(NumberUtils.isDigits(response.getBody()));
assertTrue(NumberUtils.toInt(response.getBody()) >= 0);
}
}
Fails with NullPointerException when calling restTemplate.getForEntity(...):
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.apache.commons.lang3.math.NumberUtils;
import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.*.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.client.RestTemplate;
import lombok.extern.log4j.Log4j2;
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = {TestConfig.class, RestTemplate.class})
#Log4j2
#AutoConfigurationPackage
public class Test {
#Value("${service.url.base}/bob/count")
private String countUrl;
#Autowired
private RestTemplate restTemplate;
#Test
public void testCount() throws Exception {
LOG.info(countUrl);
ResponseEntity<String> response = restTemplate.getForEntity(countUrl, String.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertTrue(NumberUtils.isDigits(response.getBody()));
assertTrue(NumberUtils.toInt(response.getBody()) >= 0);
}
}
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>
<parent>
<!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath />
</parent>
<artifactId>api-integration</artifactId>
<groupId>group.id</groupId>
<name>Integration Test</name>
<description>Integration Test</description>
<version>0.0.1-SNAPSHOT</version>
<properties>
<main.basedir>${basedir}/..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- HELPERS -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Stack Trace:
java.lang.NullPointerException
at Test.testCount(Test.java:36)
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 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Misantorp was correct.
I had to fix the import path for #Test and remove the restTemplate bean definition method from TestConfig.java.
Fix #1 - Fix Import and use RestTemplateAutoConfiguration:
Change import org.junit.Test; to import org.junit.jupiter.api.Test;
and
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = {TestConfig.class, RestTemplateAutoConfiguration.class})
#Log4j2
Fix #2 - Fix Import and use remove the bean from RestConfig:
Change import org.junit.Test; to import org.junit.jupiter.api.Test;
and
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = {TestConfig.class, RestTemplate.class})
#Log4j2
public class SecurityMarkingsTest {
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
#Configuration
public class TestConfig {
// #Bean
// public RestTemplate restTemplate(RestTemplateBuilder builder) {
// return builder.build();
// }
}
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;
}
}
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).
In EHCache, is there a way to implement some kind of a db listener where the cahce will auto update if the data is out of sync? (e.g as soon as the user requests for data, the cahce checks if the data is out of sync, if yes...updates itself and returns the data, if not...just return the data from the cache)If someone can point me which part of the specification highlights this use, that would be awesome!
The goal is to always provide the latest data to the user. So I am guessing a timed refresh mechanism will not do as the data can change anytime.
EHCAche is not mandatory to use in my case, so any mechanism that satisfies this will be most welcome...
Thanks!!
For EhCache this is what I believe you are looking for. If you would not like to do timed refresh (even though it is a simple solution), triggers or a message bus based update would be the way to go. You can perform some statistics and see update frequency once the triggering has been established and switch to a timed update with sufficient frequency to satisfy Nyquist.
I did that using ehcache-spring-annotations. These are my dependencies in the maven pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.ehcache-spring-annotations</groupId>
<artifactId>ehcache-spring-annotations</artifactId>
<version>1.2.0-M1</version>
</dependency>
#Cacheable works, but unfortunately #TriggersRemove doesn't work. The workaround is to invalidate the cache manually.
Here is my example of usage:
package com.company.project.dao;
import java.util.List;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.company.project.domain.Parent;
import com.company.project.domain.Child;
import com.googlecode.ehcache.annotations.Cacheable;
import com.googlecode.ehcache.annotations.KeyGenerator;
import com.googlecode.ehcache.annotations.Property;
#Component("Example")
public class EhcacheExample {
#Autowired
#Qualifier("ehCacheManager")
private FactoryBean<CacheManager> ehCacheManager;
public void createParen(Parent parent) {
cleanCache(parent);
create(parent);
}
private void cleanCache(Parent parent) {
try {
CacheManager cacheManager = ehCacheManager.getObject();
Ehcache ehcache = cacheManager.getEhcache("myCache");
ehcache.remove(parent.getChild().hashCode());
} catch (Exception e) {
e.printStackTrace();
}
}
#Cacheable
( cacheName = "myCache",
keyGenerator = #KeyGenerator (
name = "com.company.project.util.ChildCacheKeyGenerator",
properties = #Property( name="includeMethod", value="false" )
)
)
public List<SerieRecording> getParentsByChild(Child child) {
return ...;
}
#Override
public void deleteParentById(long id) {
Parent parent = findById(id);
cleanCache(parent);
delete(parent);
}
...
}
The KeyGenerator implementation can be:
package com.company.project.util;
import java.io.Serializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.company.project.domain.Child;
import com.googlecode.ehcache.annotations.key.AbstractCacheKeyGenerator;
public class ChildCacheKeyGenerator extends AbstractCacheKeyGenerator<Serializable> {
Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public Serializable generateKey(Object... data) {
if (data[0] instanceof Child) {
Child child = (Child)data[0];
return child.hashCode();
}
new IllegalArgumentException();
return null;
}
}
In the Spring configuration:
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" >
<property name="configLocation" value="classpath:config/ehcache-methods.xml"/>
</bean>
ehcache-methods.xml:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<cache name="myCache" eternal="false"
maxElementsInMemory="12600" overflowToDisk="false" diskPersistent="false"
timeToIdleSeconds="0" timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LRU" />
</ehcache>
I hope it is useful.