I am learning Spring and i created the following interfaces and classes all under the same package
public interface CompactDisc {
public void play();
}
-
#Component
public class StgPeppers implements CompactDisc{
private String title = "Stg. Pepper's Lonely Hearts Club Band";
private String artist = "The Beatles";
#Override
public void play(){
System.out.println("Playing "+title+" by "+artist);
}
}
-
#Configuration
#ComponentScan
public class CDPlayerConfig {
}
That are tested using
import junit.framework.Assert;
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;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
#Autowired
private CompactDisc cd;
#Test
public void cdShouldNotBeNull() {
Assert.assertNotNull(cd);
}
}
I am following these examples from a book, it asks to test that it's working but not how to do that so i created under the same package a main class that just does that
public class Main {
public static void main(String[] args){
new CDPlayerTest().cdShouldNotBeNull();
}
}
In the console i have
Exception in thread "main" junit.framework.AssertionFailedError
at junit.framework.Assert.fail(Assert.java:55)
at junit.framework.Assert.assertTrue(Assert.java:22)
at junit.framework.Assert.assertNotNull(Assert.java:256)
at junit.framework.Assert.assertNotNull(Assert.java:248)
at automaticWiring.CDPlayerTest.cdShouldNotBeNull(CDPlayerTest.java:30)
at automaticWiring.Main.main(Main.java:17)
All the imports of the classes are correct even if omitted, i am using a Netbeans webapp with Spring Web MVC framework, i also had to add JUnit 4.12 jar to the library since it wasn't there at the beginning.
Is there something wrong with the Spring code or is my testing method incorrect ?
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>
You could try this :
#RunWith(SpringRunner.class)
#SpringBootTest
public class CDPlayerTest {
#Autowired
private CompactDisc cd;
...
}
Keep in mind that the test-class loads the entire application context whene before executing the tests.
Related
There are REST web service based on Jersey 2.23.2 & Guice 3.0. To use Guice it is necessary to adjust the hk2-guice bridge (I'm using 2.5.0-b07). Everything works fine until I have tried to test the service using Jersey Test Framework. Can't configure hk2-guice bridge for tests.
My test:
public class SomeTest extends JerseyTestNg.ContainerPerClassTest {
#Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new GrizzlyWebTestContainerFactory();
}
#Override
protected Application configure() {
return super.configure(); // cant't configure
}
#Test
public void test() {
Assert.assertEquals(1, 1);
}
}
I can't configure test in SomeTest.configure() just returning new JerseyConfiguration() (see below) because JerseyConfiguration's constructor expected ServiceLocator's object.
Even if it were possible to return an object of class `JerseyConfiguration` - I'm not sure that my test would work because some filters and listener are defined in the web.xml file.
How to configure the test taking into account all filters, listener and hk2-guice bridge?
Web service details
Dependencies section from build.gradle:
def jerseyVersion = '2.23.2'
def hk2Version = '2.5.0-b07'
def giuceVersion = '3.0'
dependencies {
compile "javax.servlet:javax.servlet-api:3.1.0"
//jersey
compile "org.glassfish.jersey.core:jersey-server:${jerseyVersion}"
compile "org.glassfish.jersey.containers:jersey-container-servlet:${jerseyVersion}"
//hk2
compile "org.glassfish.hk2:guice-bridge:${hk2Version}"
//guice
compile "com.google.inject:guice:${giuceVersion}"
compile "com.google.inject.extensions:guice-servlet:${giuceVersion}"
}
File web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>REST API App</display-name>
<listener>
<listener-class>com.example.core.JerseyGuiceServletContextListener</listener-class>
</listener>
<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>
<filter>
<filter-name>jerseyFilter</filter-name>
<filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.example.core.JerseyConfiguration</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jerseyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Class JerseyGuiceServletContextListener:
public class JerseyGuiceServletContextListener extends GuiceServletContextListener {
static Injector injector;
#Override
protected Injector getInjector() {
injector = Guice.createInjector(new JerseyServletModuleConfig());
return injector;
}
}
Class JerseyServletModuleConfig:
class JerseyServletModuleConfig extends ServletModule {
#Override
protected void configureServlets() {
bind(HeyResource.class).in(Scopes.SINGLETON);
}
}
Class JerseyConfiguration:
package com.example.core;
import com.google.inject.Injector;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.server.ResourceConfig;
import org.jvnet.hk2.guice.bridge.api.GuiceBridge;
import org.jvnet.hk2.guice.bridge.api.GuiceIntoHK2Bridge;
import javax.inject.Inject;
import javax.servlet.ServletContext;
class JerseyConfiguration extends ResourceConfig {
#Inject
public JerseyConfiguration(ServiceLocator serviceLocator, ServletContext servletContext) {
packages("com.example.ws");
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(JerseyGuiceServletContextListener.injector);
}
}
just overrode configureDeployment() & modified configure() methods in test
public class SomeTest extends JerseyTestNg.ContainerPerClassTest {
#Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new GrizzlyWebTestContainerFactory();
}
#Override
protected Application configure() {
return new ResourceConfig()
.packages("com.example.ws")
.register(GensonCustomResolver.class);
}
#Override
protected DeploymentContext configureDeployment() {
Application application = configure();
return ServletDeploymentContext.builder(application)
.addListener(JerseyGuiceServletContextListener.class)
.addFilter(GuiceFilter.class, "guiceFilter")
.addFilter(ServletContainer.class, "jerseyFilter", new HashMap<String, String>(){{
put("javax.ws.rs.Application", JerseyConfiguration.class.getCanonicalName());
}})
.build();
}
#Test
public void test() {
Assert.assertEquals(1, 1);
}
}
& add web.xml to test classpath.
I am pretty new to spring. I have dynamic web application project. Inside i have a servlet which is receive request. The request comes with a request no. Based on the no i will create a new object for appropriate request class and serve the request. Now i need to integrate with spring. i applied the below configuration,
WEB.XML (To load spring context)
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/docspring.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
In servlet
package com.receve;
#Controller
#WebServlet("/Recever")
public class Recever extends HttpServlet {
#Autowired
private ClassOne one;
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//request parameters receved and
if(req==1){
one.print();
}
}
public ClassOne getOne() {
return One;
}
public void setOne(ClassOne one) {
this.one = one;
}
}
In ClassOne
package com.operations;
#Component
public Class ClassOne{
public void print(){
//some statement;
}
}
In spring.xml
<context:annotation-config />
<context:component-scan base-package="com" />
But while running the application i am getting NullPointerexception while calling one.print() method. what is the proper way(configuration) to obtain this?
Thanks.
Remove extends HttpServlet and Autowiring is turned off by default, so the default autowiring mode for a bean is 'no'.
I'm trying to implement an application with several uis - vaadin, jsp and etc.
It was working with simple jsp but then I decided to use vaadin as ui.
I've created vaadin servlet(and spring servlet left too).
My web.xml looks like this
<?xml version="1.0"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/pmc-web-context.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>another-pmc-servlet</servlet-name>
<servlet-class>com.vaadin.server.VaadinServlet</servlet-class>
<init-param>
<param-name>UI</param-name>
<param-value>com.xxxx.app.pmc.vaadin.PmcUi</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>pmc-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>another-pmc-servlet</servlet-name>
<url-pattern>/VAADIN/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>pmc-servlet</servlet-name>
<url-pattern>/JSP/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>/WEB-INF/jsp/*</url-pattern>
</servlet-mapping>
</web-app>
I've created vaadin table component and adjusted it for my needs. I used autowiring for service.
package com.xxxx.app.pmc.vaadin.components;
import com.xxxx.app.pmc.model.Project;
import com.xxxx.app.pmc.service.project.ProjectService;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.ui.Table;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
#Component("projectTable")
public class ProjectTable extends Table {
private static final String CAPTION = "Projects";
private static final String[] headers = { "Project name", "Project owner", "ID" };
#Autowired
private ProjectService projectService;
public Table createTable() {
this.setContainerDataSource(projectDatasource());
this.setVisibleColumns(headers);
this.setSelectable(true);
this.setImmediate(true);
return this;
}
public IndexedContainer projectDatasource() {
IndexedContainer indexedContainer = new IndexedContainer();
for(String header: headers) {
indexedContainer.addContainerProperty(header, String.class, "");
}
List<Project> projects = projectService.findAllProjects();
for(int i = 0; i < projects.size(); i++) {
Object id = indexedContainer.addItem();
Project item = projects.get(i);
indexedContainer.getContainerProperty(id, headers[0]).setValue(item.getProjectName());
indexedContainer.getContainerProperty(id, headers[1]).setValue(item.getProjectOwner());
indexedContainer.getContainerProperty(id, headers[1]).setValue(item.getProjectId());
}
return indexedContainer;
}
}
ProjectService is a spring bean too.
#Service("projectService")
public class ProjectService {
#Autowired
private ProjectRepository projectRepository;
public void insertProject(Project project) {
projectRepository.store(project);
}
public List<Project> findAllProjects() {
return projectRepository.getAllItems();
}
public Project getProject(String id) {
return projectRepository.get(id);
}
}
ProjectRepository is another spring bean. It uses SqlSessionTemplate bean from MyBatis.
#Repository("projectRepository")
public class ProjectRepository implements IRepository<Project> {
private static final String STORE_PROJECT = "Project.insertProject";
private static final String GET_PROJECT_BY_ID = "Project.getProjectById";
private static final String GET_PROJECT_LIST = "Project.getProjectList";
#Autowired
private SqlSessionTemplate sqlSessionTemplate;
#Override
public void store(Project object) {
sqlSessionTemplate.insert(STORE_PROJECT, object);
}
#Override
public Project get(String id) {
return sqlSessionTemplate.selectOne(GET_PROJECT_BY_ID, id);
}
#Override
public List<Project> getAllItems() {
return sqlSessionTemplate.selectList(GET_PROJECT_LIST);
}
}
When I wrote an application using spring controller(using JSP) - it was working fine.
But when I added vaadin - JSP stopped working and vaadin application throws NullPointerException for ProjectService, ProjectRepository... all the beans I use.
What is the problem?
All my context xml context files are simple.
<import resource="classpath:com/xxxx/app/pmc/pmc-service-context.xml"/>
<context:component-scan base-package="com.xxx.app.pmc"/>
And my pmc-web-context.xml has this lines too.
<mvc:annotation-driven/>
<context:annotation-config/>
It was working fine with JSP so I think the problem is not with spring declarations itself but with integration of spring into vaadin of mine.
How to resolve it?
When I for example created ProjectTable object manually - it throws NullPointerException for ProjectService. When I create ProjectService manually - it throws NullPointerException for ProjectRepository and so on. It seems autowiring simply doesn't work.
P.S forgot to add my UI code
package com.xxxx.app.pmc.vaadin;
import com.xxxx.app.pmc.vaadin.components.ProjectTable;
import com.vaadin.annotations.Title;
import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import org.springframework.stereotype.Component;
#Title("PMC")
#Component("pmcVaadin")
public class PmcUi extends UI {
#Override
protected void init(VaadinRequest request) {
VerticalLayout mainLayout = new VerticalLayout();
ProjectTable projectTable = new ProjectTable();
mainLayout.addComponent(projectTable.createTable());
mainLayout.setSizeFull();
setContent(mainLayout);
}
}
Like you suspected your Spring beans are created, but in application and Spring's servlet contexts. Your Vaadin servlet has no access to any of those.
For detailed (manual) solution with code either check Vaadin's wiki or search for a proper Vaadin's add ons that will do the job for you (personally I recommend SpringVaadinIntegration).
The typical idea is to programmatically pass Vaadin servlet to one of Spring's utility classes (eg.: WebApplicationContextUtils) and retrieve application context (loaded by ContextLoaderListener). If you need servlet context, then from code examples I have seen, you do the same as above, but additionally manually read context (eg.: using XmlWebApplicationContext) and set application context as it's parent.
Pretty easy option is to use Configurable support. It'll do some aspect magic and all java objects annotated by #Configurable will be automatically integrated into Spring. You can find more details in Spring documentation. Also please note that to represent context information in GUI you will have to use session beans. That causes the problem with session size, and in bigger applications makes it impossible to cluster.
I am having some difficulty auto-wiring beans into a class which is loaded as an init-param in a servlet for OData4j. I have tried many solutions including load-time-weaving but cannot seem to get it to work correctly because as I understand it, the class which is being passed as an init-param to the servlet is being loaded prior to Spring context being loaded at all. Below is the current state of my configuration, is there a way to have dependency injection in a class loaded in such a way? The end goal is to have the ExampleProducerFactory.java (which is an init-param of the OData servlet) having the UserDao bean autowired.
I have tried to just include the key pieces of each of these files, if there is additional configuration information needed, please comment.
applicationContext.xml
<context:component-scan base-package="com.project.core"/>
<context:spring-configured/>
<context:load-time-weaver weaver-class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" />
web.xml
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- read the XmlWebApplicationContext for spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>OData</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
<param-value>org.odata4j.producer.resources.ODataResourceConfig</param-value>
</init-param>
<init-param>
<param-name>odata4j.producerfactory</param-name>
<param-value>com.wildgigs.core.odata.ExampleProducerFactory</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>OData</servlet-name>
<url-pattern>/example.svc/*</url-pattern>
</servlet-mapping>
ExampleProducerFactory.java
#Configurable(autowire= Autowire.BY_NAME)
public class ExampleProducerFactory implements ODataProducerFactory {
#Autowired
private UserDao userDao;
#Override
public ODataProducer create(Properties arg0) {
InMemoryProducer producer = new InMemoryProducer("example");
List<User> users = userDao.findAll();
User[] usersArray = new User[users.size()];
users.toArray(usersArray);
final User[] usersArrayFinal = usersArray;
producer.register(User.class, Long.class, "Users", new Func<Iterable<User>>() {
public Iterable<User> apply() {
ThreadGroup tg = Thread.currentThread().getThreadGroup();
while (tg.getParent() != null)
tg = tg.getParent();
return Enumerable.create(usersArrayFinal).take(usersArrayFinal.length);
}
}, "Id");
return producer;
}
}
UserDaoImpl.java
#Repository
public class UserDaoImpl extends GenericDaoImpl<User, Long> implements UserDao, Serializable {
#Transactional(readOnly = true)
public User getByUserName(String userName) {
Query query = getSession().createQuery("FROM User where upper(userName) = :name");
query.setString("name", userName.toUpperCase());
return (User) query.uniqueResult();
}
}
You should use the jersey SpringServlet instead of the ServletContrainer. With that instead of specifying resourceConfig in the init param you can define it as a spring bean.
A bean must be created in your spring config to inject into your class.
<bean id="userDao" class="com.yourdomain.pacakage.UserDao">
In my web.xml I have
<filter>
<filter-name>authFilter</filter-name>
<filter-class>com.mystuff.AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>authFilter</filter-name>
<servlet-name>requestFactoryServlet</servlet-name>
</filter-mapping>
<!-- Servlets -->
<servlet>
<servlet-name>requestFactoryServlet</servlet-name>
<servlet-class>com.google.web.bindery.requestfactory.server.RequestFactoryServlet</servlet-class>
<init-param>
<param-name>symbolMapsDirectory</param-name>
<!-- You'll need to compile with -extras and move the symbolMaps directory
to this location if you want stack trace deobfuscation to work -->
<param-value>WEB-INF/classes/symbolMaps/</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>requestFactoryServlet</servlet-name>
<url-pattern>/gwtRequest</url-pattern>
</servlet-mapping>
and I am attempting to convert this to use Guice Servlet configuration rather than the web.xml configuration.
I cannot figure out how to do the equivalent of the of the in Guice. I only see examples of how to filter patterns, not specific servlets.
Define a Guice listener in web.xml :
<listener>
<listener-class>xxx.GuiceServletConfig</listener-class>
</listener>
And implement this listener :
public class GuiceServletConfig extends GuiceServletContextListener {
#Override
protected Injector getInjector() {
return Guice.createInjector(new ServletModule() {
#Override
protected void configureServlets() {
Map<String, String> params = new HashMap<String, String>();
params.put("symbolMapsDirectory", "WEB-INF/classes/symbolMaps/");
serve("/gwtRequest").with(RequestFactoryServlet.class, params);
}
});
}
}