Spring: context-component-scan is not working - spring

There are lots of question have been asked around this question, but I am still not getting the root cause of what is preventing my bean to be autowired.
I have following level of packages:
com.pack.amg.service
com.pack.amg.repository
com.pack.amg.beans
com.pack.amg.resources
applicationContext.xml (which is required by ContextLoaderListner in web.xml)
<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:neo4j="http://www.springframework.org/schema/data/neo4j"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/data/neo4j
http://www.springframework.org/schema/data/neo4j/spring-neo4j-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:component-scan base-package="com.pack.amg" />
<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
<constructor-arg value="http://localhost:7474/db/data/" index="0" />
</bean>
<neo4j:config graphDatabaseService="graphDatabaseService"
base-package="com.pack.amg.repository" />
<neo4j:repositories base-package="com.pack.amg.repository" />
<tx:annotation-driven mode="proxy" />
I am expecting here to auto scan all of my packages and subpackages and its classes using <context:component-scan base-package="com.pack.amg" /> which may be true but is not working at all..! Following is my REST resource:
TestResource.java
#Path("/")
#Service
public class TestResource
{
#Autowired
private MyService myService;
#Path("/save")
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response getResponse(ParamBeans bean)
{
System.out.println(bean);
String str = myService.save(bean); // <-- here myService is evaluating as null !!
return Response.ok(str).build();
}
}
MyService.java
#Service
public class MyService
{
#Autowired
private MyRepository repository;
public String save(ParamBeans bean)
{
return "Saved";
}
}
My war is deploying properly without any Exception, but while calling my REST service, it evaluating MyService as null. does anyone know why ? Thanks

M.Deinum is correct. You must need to make your Spring aware of your jersey. I had the same issue before, You need to add additional dependency and configuration in pom.xml as below:
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-spring</artifactId>
<version>1.18.1</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
and replace your old implementation of Jersey servlet from web.xml with following one:
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.your.package.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern> <!-- depending upon your choice -->
</servlet-mapping>
Where com.sun.jersey.spi.spring.container.servlet.SpringServlet belongs to latest dependency added i.e. jersey-spring. Hope this helps
Update
As suggested by cronemberger, there seems some issues with Jersey 2 lib. So it may happen above implementation may not work with Jersey 2, but I need to check with the same.

Related

Upgrading to switch from JSON/XML marshalling in order to use Jackson 2

I am currently using Spring - and am using Jersey's old technologies to marshall and unmarshall - I need to upgrade the marshalling library to the latest version in order to use Jackson.
I have usually got some code to show, but obviously in this scenario - I am not even sure where to begin, so if anyone can help out that would be cool.
WEB.XML CONFIGURATION FOR JERSEY :
<servlet>
<description>Jersey Servlet</description>
<servlet-name>jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
POM :
<jersey.version>1.4</jersey.version>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-spring</artifactId>
<version>${jersey.version}</version>
<scope>runtime</scope>
<!-- exclude spring dependencies so can pin to our desired versions (esp. spring-web) -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
If you want to use Jackson 2, you should first get rid of the jersey-json, then add the following
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson2.version}</version>
<!-- latest right now is 2.8.3 -->
</dependency>
Then in your servlet configuration, add the Jackson package to the list of packages to scan.
<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>
your.packages,
com.fasterxml.jackson.jaxrs.json <!-- add jackson -->
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Note that if you are using a Jackson version newer than 2.7.0, the above package will not include the Jackson ExceptionMappers. According to this issue, it seems they are now removed and also the #Provider annotations have been removed. So we can't package scan for them.
So if you do want the mappers, you should declare them by class.
<param-name>
com.sun.jersey.config.property.classnames
</param-name>
<param-value>
com.fasterxml.jackson.jaxrs.base.JsonMappingExceptionMapper,
com.fasterxml.jackson.jaxrs.base.JsonParseExceptionMapper
</param-value>
I should mention though, that it's really recommended to write your own mappers. The response the these mappers spit out, is the exception message, and that's not really something you want as the error response.
You will need to update your POM to include the jackson jars(core, databind, annotaion) in https://mvnrepository.com/artifact/com.fasterxml.jackson.core. You will also need to do the below for converting JSON to Java object and vice versa
<beans:bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<beans:property name="messageConverters">
<beans:list>
<beans:ref bean="jsonMessageConverter" />
</beans:list>
</beans:property>
</beans:bean>
<!-- Configure bean to convert JSON to POJO and vice versa -->
<beans:bean id="jsonMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</beans:bean>
You would need to create a class with variables that are named after the "keys" in JSON. The code to convert JSON string to object of the JAVA class would be as below:
Suppose JSON is
{
'name' : 'Test',
'userId' : 'test101'
}
The Java class corresponding to this would be:
public class Test {
private String name;
private String userId;
// Write getter and setter methods for each variable.
}
The code for converting JSON string to the object of Test class would be:
ObjectMapper mapper = new ObjectMapper();
String jsonInString = ""{'name' : 'Test', 'userId' : 'test101'}"";
//JSON from String to Object
Test obj = mapper.readValue(jsonInString, Test.class);
obj.getName() would give value corresponding to the key.

How to configure Spring Repository to use mongoTemplate defined in xml bean?

The code executes fine, but creates collections in default mongo database and location i.e in test database # localhost:27017. In the mongoTemplate bean wired through the below xml, I'm using mydb as database with mongod instance running at localhost:27018. However, the data still gets persisted to default instance and database.
MongoDB XML Bean defined in src/main/resources/mongo-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:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<mongo:mongo id="mongo" host="localhost" port="27018"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongo" />
<constructor-arg value="mydb" />
</bean>
<mongo:repositories base-package="core.repository" mongo-template-ref="mongoTemplate"/>
</beans>
Playlist repository:
package core.repository;
import core.dao.Playlist;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.repository.Repository;
/**
* This repository provides CRUD operations for {#link core.dao.Playlist} objects.
*/
public interface PlaylistRepository extends Repository<Playlist, String> {
/**
* Finds the information of a single Playlist entry.
* #param id The id of the requested Playlist entry.
* #return The information of the found Playlist entry. If no Playlist entry
* is found, this method returns an empty {#link java.util.Optional} object.
*/
Optional<Playlist> findOne(String id);
/**
* Saves a new Playlist entry to the database.
* #param saved The information of the saved Playlist entry.
* #return The information of the saved Playlist entry.
*/
Playlist save(Playlist saved);
}
Playlist service that uses repository:
package core.service;
import core.dao.*;
import core.error.NotFoundException;
import core.repository.PlaylistRepository;
import core.simulator.PlaylistServiceSimulator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Executes the business logic promised by the {#link core.service.PlaylistService} interface.
*/
#Service
final class PlaylistServiceExecutor implements PlaylistService {
private static final Logger LOGGER = LoggerFactory.getLogger(PlaylistServiceExecutor.class);
private final PlaylistRepository repository;
private final PlaylistServiceSimulator simulator;
#Autowired
PlaylistServiceExecutor(PlaylistRepository repository, PlaylistServiceSimulator simulator) {
this.repository = repository;
this.simulator = simulator;
}
#Override
public PlaylistDTO create(PlaylistDTO playlist) {
LOGGER.debug("Creating a new Playlist entry with information: {}", playlist);
Playlist persisted = Playlist.build()
persisted = repository.save(persisted);
LOGGER.debug("Created a new Playlist entry with information: {}", persisted);
return persisted.toDTO();
}
#Override
public PlaylistDTO findById(String id) {
LOGGER.debug("Finding Playlist entry with id: {}", id);
Playlist found = findPlaylistById(id);
LOGGER.debug("Found Playlist entry: {}", found);
return found.toDTO();
}
private Playlist findPlaylistById(String id) {
Optional<Playlist> result = repository.findOne(id);
return result.orElseThrow(() -> new NotFoundException(id));
}
}
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>
<groupId>myapp</groupId>
<artifactId>core</artifactId>
<version>0.1</version>
<properties>
<!-- Enable Java 8 -->
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Configure the main class of our Spring Boot application -->
<start-class>core.CoreApp</start-class>
</properties>
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.9.RELEASE</version>
</parent>
<dependencies>
<!-- Get the dependencies of a web application -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<!-- Spring Data MongoDB-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>1.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>0.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-assert</artifactId>
<version>0.9.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot Maven Support -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Finally, SpringApplication boot class CoreApp:
package core;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* This configuration class has three responsibilities:
* <ol>
* <li>It enables the auto configuration of the Spring application context.</li>
* <li>
* It ensures that Spring looks for other components (controllers, services, and repositories) from the
* <code>core</code> package.
* </li>
* <li>It launches our application in the main() method.</li>
* </ol>
*/
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class CoreApp {
public static void main(String[] args) {
SpringApplication.run(CoreApp.class, args);
}
}
I'm assuming you're using Spring boot for it's auto configuration features and opinionated defaults. If so, you should let Spring configure your Mongo repository.
Remove your mongo configuration in src/main/resources/mongo-context.xml
Replace the mongo dependency
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
with the following Spring boot dependency to pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
Make sure your repositories extend MongoRepository
Have at least the following properties in your application.properties. See Spring Boot appendix for properties reference
spring.data.mongodb.uri=mongodb://localhost:27018/mydb
spring.data.mongo.repositories.enabled=true
Here are some additional guides:
https://spring.io/guides/gs/accessing-data-mongodb/
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-nosql.html
You can use applicationContext.xml file for this. It looks like below:
<?xml version="1.0" encoding="UTF-8"?>
<beans default-lazy-init="true" 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:util="http://www.springframework.org/schema/util" xmlns:security="http://www.springframework.org/schema/security" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo.xsd">
<description><![CDATA[
Main entry point for spring configuration
]]></description>
<!-- Connection to MongoDB server -->
<mongo:db-factory host="localhost" port="27017" dbname="test" />
<!-- MongoDB Template -->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>
<!-- Package w/ automagic repositories -->
<mongo:repositories base-package="com.bedas.ays.mongo" />
</beans>

Spring AOP advice not getting excuted

I am new to Spring AOP and facing some issues in its implementation.
I am trying to implement logging as advice. But advice is not getting executed.
Following is the files I am using.
LoggingAspect.java
package com.demo.conference.aspects;
#Aspect
#Component
public class LoggingAspect {
#Pointcut("execution(* com.demo.conference.daoImpl.ConferenceDAOImpl.*(..))")
public void point(){}
#Pointcut("execution(public * *(..))") //this should work for the public pointcut
private void anyPublicOperation() {}
#Before("anyPublicOperation()")
public void log(){
System.out.println("--------------------->Aspect execuetd");
}
}
dispatcher-servlet.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:annotation-config/>
<mvc:annotation-driven />
<context:component-scan base-package="com.demo.conference"/>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
</beans>
applicationContext.xml // For AOP related config
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="com.demo.conference.aspects"/>
<aop:aspectj-autoproxy/>
</beans>
web.xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<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>
</web-app>
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
Firstly i was putting all xml configurations in single file(in dispatcher-servlet.xml), then it was throwing exception NoSuchBeanDefined.
Then i found in some post to declare AOP related config in seperate file. I did so.(If any one can explain the reason behind creating seperate files)
Now there is not any exception but Advice is not getting executed.
Updated
package com.demo.conference.daoImpl;
#Component
#Repository
public class ConferenceDAOImpl implements ConferenceDAO {
#Autowired
private HibernateTemplate hibernateTemplate;
/**
* Method to list all the conferences
* #return list of conferences
*/
public List<Conference> listConference() {
System.out.println("***ConferenceDAOImpl : listConference");
System.out.println("Before fetching conferences");
List<Conference> conferenceList = hibernateTemplate.find("from "+ Conference.class.getName());
return conferenceList;
}
}
In dispatcher-servlet.xml change the component scan to com.demo.conference.serviceControllers and in applicationContext.xml change the component scan to com.demo.conference.
HibernateTemplate and other beans which are not web related shouldn't be placed in dispatcher-servlet.xml. These should be in applicationContext.xml. In dispatcher-servlet.xml you should have controllers, view resolvers and other beans related to web part only. Move any other beans to applicationContext.xml and configure the component-scans as I mentioned: in dispatcher-servlet.xml use com.demo.conference.serviceControllers, in applicationContext.xml use com.demo.conference.
The story is like this: beans in dispatcher-servlet.xml form an application context which has as a parent the application context formed by beans in applicationContext.xml. When a bean is needed by something in dispatcher-servlet context it is searched in the containing context, if it's not found it is searched in parent contexts. So, every bean defined in applicationContext.xml should be easily accessible by beans in dispatcher-servlet context. But not vice-versa. Beans in applicationContext cannot access beans in dispatcher-servlet.
Also, use #Autowired with the interfaces, not the concrete class: #Autowired private ConferenceDAO dao; and #Autowired private ConferenceService service; and restrict the range of your pointcut (use point() instead and comment anyPublicOperation())! Beans like HibernateTemplate are advised, as well, and Spring is creating a proxy for it. If you are injecting HibernateTemplate which is a concrete class in your own classes, the proxy which is created is a JDK proxy (which implements an interface) whereas #Autowired expects an instance of HibernateTemplate.

org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:403)

I have run into this "WELD-001408 Unsatisfied dependencies for type [Injector] with qualifiers..." error when deploying a Maven project to Glassfish 4. I searched on the internet and added scope, added bean-discovery-mode="all", all other things and still could not get it work. I am learning Spring Framework and Java EE. Would someone please take a look at my code and help me out? Thanks!
stacktrace:
2014-01-28T11:29:44.755-0600|SEVERE: Exception while loading the app
2014-01-28T11:29:44.755-0600|SEVERE: Undeployment failed for context /MessageBoard
2014-01-28T11:29:44.786-0600|SEVERE: Exception while loading the app : CDI deployment failure:Exception List with 2 exceptions:
Exception 0 :
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Injector] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedMethod] #Inject org.eclipse.sisu.inject.DefaultBeanLocator.autoPublish(Injector)]
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:403)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:325)
at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:177)
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:208)
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:519)
at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:505)
at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:480)
at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:536)
at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:216)
at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:131)
at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:328)
codes:
package com.aaa.chapter5;
public class MessageBoardServiceImpl implements MessageBoardService {
private Map<Long, Message> messages = new LinkedHashMap<Long, Message>();
public List<Message> listMessages() {
return (List)messages.values();
}
public synchronized void postMessages(Message message) {
Long id = System.currentTimeMillis();
message.setId(id);
messages.put(id, message);
}
}
package com.aaa.chapter5.web;
// Bind controller to URL /reservationForm
// initial view will be resolved to the name returned in the default GET method
#Controller
#RequestMapping("/messagePost*")
#RequestScoped
//#SessionAttributes("message") // Command name class was used in earlier Spring versions
public class MessagePostController {
private MessageBoardService messageBoardService;
#Autowired
public void MessagePostController(MessageBoardService messageBoardService) {
this.messageBoardService = messageBoardService;
}
// Controller will always look for a default GET method to call first, irrespective of name
// In this case, named setupForm to ease identification
#RequestMapping(method = RequestMethod.GET)
public String setupForm(Model model) {
// Create inital message object
Message message = new Message();
// Add message to model so it can be display in view
model.addAttribute("message", message);
return "messagePost";
}
#RequestMapping(method = RequestMethod.POST)
public String onSubmit(#ModelAttribute("message") Message message, BindingResult result) { //, SessionStatus status) {
if (result.hasErrors()) {
// Errors, return to Form view
return "messagePost";
} else {
// No errors make reservation
messageBoardService.postMessages(message);
// Set complete, mark the handler's session processing as complete
// Allowing for cleanup of session attributes.
//status.setComplete();
// Redirect to reservationSuccess URL, defined in ReservationSuccessController
return "redirect:messageList";
}
}
}
pom.xml:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.aaa.chapter5</groupId>
<artifactId>MessageBoard</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>MessageBoard Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<glassfish.directory>C:/Tools/glassfish4/glassfish</glassfish.directory>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.servlet.jsp.jstl</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>3.0-alpha-2</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.maven.plugin</groupId>
<artifactId>maven-glassfish-plugin</artifactId>
<version>2.1</version>
<type>maven-plugin</type>
</dependency>
web.xml
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/board-service.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>board</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>board</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
board-service.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.aaa.chapter5" />
<mvc:annotation-driven />
board-servlet.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.aaa.chapter5.web"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
<bean id="messageBoard"
class="com.aaa.chapter5.MessageBoardServiceImpl">
</bean>
</beans>

Spring DI - Autowired property is null in a REST service

I'm getting started with Spring DI, but I'm struggling with dependency injection and the worse part is that I'm not even sure why as it seems ok to me. Hopefully you guys can help me out!
The problem is that a property annotated as #Autowired is always null
I've got a few projects with Maven structure:
com.diegotutor.lessondeliver
com.diegotutor.utility
I'm running the examples over Tomcat 7
I'm using the following dependencies in my pom.xml:
spring-context 3.2.4
spring-web 3.2.4
jersey-server 1.17.1
jersey-core 1.17.1
jersey-servlet 1.17.1
The simple idea is to have a RESTful service that through Dependency Injection is able to print out the value of a property located in a config file located at: D:\configuracion.conf.
At com.diegotutor.utility I have the following interface:
package com.diegotutor.utility;
public interface ConfigService {
public String getProperty(final String propertyName);
}
Implemented by:
package com.diegotutor.utility.impl;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import com.diegotutor.utility.ConfigService;
public class PropertyFileConfigService implements ConfigService{
Properties prop;
public PropertyFileConfigService (final InputStream input) throws IOException {
if(input == null) {
throw new IllegalArgumentException("Input stream can't be null");
}
prop = new Properties();
prop.load(input);
}
public PropertyFileConfigService (final String fileName) throws IOException {
final FileInputStream input = new FileInputStream(fileName);
prop = new Properties();
prop.load(input);
}
public PropertyFileConfigService(final Reader input) throws IOException {
prop = new Properties();
prop.load(input);
}
public String getProperty(final String propertyName) {
return prop.getProperty(propertyName);
}
}
And at com.diegotutor.lessondeliver I have the RESTful service where I would like to use an injected instance of the ConfigService:
package com.diegotutor.lessondeliver;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.diegotutor.utility.ConfigService;
#Path("/")
#Component
public class HelloWorld {
private static final Log log = LogFactory.getLog(HelloWorld.class);
#Autowired
private ConfigService configService;
#Path("/helloworld")
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getHello() {
String host = configService.getProperty("host");
return "Hello World! HOST" + host;
// configService IS NULL!!
//SO IT THROWS A NULLPOINTER EXCEPTION WHEN INVOKING getProperty ON IT
}
}
Finally at /com.diegotutor.lessondeliver/src/main/webapp/WEB-INF/service-beans.xml I have the following XML application context file, where I use the implementation of ConfigService (PropertyFileConfigService) injecting on it the path for the configuration file to read:
<?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:context="http://www.springframework.org/schema/context"
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">
<bean id="configService" class="com.diegotutor.utility.impl.PropertyFileConfigService">
<constructor-arg type="java.lang.String"
value="D:\configuracion.conf" />
</bean>
<context:component-scan base-package="com.diegotutor" />
</beans>
Obviously I have specified in the web.xml of this com.diegotutor.lessondeliver web app that I want service-beans.xml as ConfigLocation and a listener ContextLoaderListener, and the RESTful service relies on ServletContainer
If I'm specifying context:component-scan to look for Components in com.diegotutor as suggested here and I'm forcing object creation through Spring by not using any new Statement as suggested here, Why am I getting the annotated configService as null? Why Spring is unable to inject an instance of com.diegotutor.utility.impl.PropertyFileConfigService?
Any help will be much appreciated!
Thank you
EDITED:
As requested, my web.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>com.diegotutor.lessondeliver</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/service-beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
You were right!
It seems that the problem is that Jersey is totally unaware of Spring and instantiates its own object. In order to make Jersey aware of Spring object creations (through dependency injection) I had to integrate Spring + Jersey.
To integrate:
Add maven dependencies
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-spring</artifactId>
<version>1.17.1</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>
</dependency>
Use SpringServlet for jersey-servlet in web.xml
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>
com.sun.jersey.spi.spring.container.servlet.SpringServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
Now the #Autowired works properly and the object is not null anymore.
I'm a little bit confused about the exclusions I have to use in maven when using jersey-spring dependency, but that's another issue :)
Thank you!
Integration Spring with Jersey 2 (org.glassfish.*):
Maven
Some dependencies may be unnecessary, please check & clear it after things got working.
<properties>
<jersey.version>2.5</jersey.version>
</properties>
<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" -->
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-inmemory</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- Jersey + Spring -->
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>${jersey.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
web.xml
<servlet>
<servlet-name>my-rest-service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>my.package.with.rest.services</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>my-rest-service</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
applicationContext.xml
During the Spring upgrading I had to move it from /main/webapp/WEB-INF/ to /main/resources/ (details).
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="my.package.with.rest.services" />
</beans>
Example REST service
public interface MyService
{
String work(String s);
}
...
#Service
public class MyServiceImpl implements MyService
{
#Override
public String work(String s)
{
return "Hello, " + s;
}
}
...
#Path("demo/")
#Component
public class DemoRestService
{
#Autowired
private MyService service;
#GET
#Path("test")
public Response test(#FormParam("param") String par)
{
try
{
String entity = service.work(par);
return Response.ok(entity).build();
}
catch (Exception e)
{
e.printStackTrace();
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Epic REST Failure").build();
}
}
}
or you can simply extend SpringBeanAutoWiringSupport class. Like this: public class DemoRestService extends SpringBeanAutoWiringSupport. By extending this support class, properties of your service class can be auto-wired.
Another possible option is to manually invoke autowiring in your jersey resource:
#Context
private ServletContext servletContext;
#PostConstruct
public void init() {
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, servletContext);
}
Hmm, you get a "manual autowiring"...

Resources