I am using Spring and Hibernate and I am successfully autowiring a Repository inside the contructor of a Service class. When i try to add #Transactional methods in my Service class i get an AopConfigException that it is about the generation of CGLib class.
My Configuration consists in 3 files.
An AppInitializer class that implements WebApplicationInitializer , a WebMvcConfig class that extends WebMvcConfigurerAdapter and lastly a PersistentContext class.
AppInitializer
public class AppInitializer implements WebApplicationInitializer {
private static final String CONFIG_LOCATION = "com.project.app.config";
private static final String MAPPING_URL = "/";
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet",
new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping(MAPPING_URL);
}
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation(CONFIG_LOCATION);
return context;
}
WebMvcConfig
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = { "com.project.app" })
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Autowired
private Environment env;
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("hello");
}
#Bean
public ApplicationContextProvider applicationContextProvider() {
return new ApplicationContextProvider();
}
}
PersistentContext
#Component
#EnableJpaRepositories("com.project.app.services.repositories")
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class PersistenceContext {
#Autowired
private Environment env;
#Bean
#Primary
public DataSource dataSource() throws ClassNotFoundException {
DataSource ds = new DataSource();
ds.setUrl(env.getProperty(SystemSettings.DS_URL));
ds.setUsername(env.getProperty(SystemSettings.DS_USERNAME));
ds.setPassword(env.getProperty(SystemSettings.DS_PASSWORD));
ds.setDriverClassName(env.getProperty(SystemSettings.DS_DRIVER));
return ds;
}
#Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan("com.project.app.services.entities");
// .. Set Properties..
entityManagerFactoryBean.setJpaProperties(jpaProperties);
return entityManagerFactoryBean;
}
#Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
}
The Repository INTERFACE extends CrudRepository
StopRepository
#Repository
#RepositoryRestResource(collectionResourceRel = "stop", path = "stop")
public interface StopRepository extends CrudRepository<StopJPA, Long> {
#Override
StopJPA save(StopJPA persisted);
}
The Entity class.
StopJPA
#Entity
#Table(name = "stop")
public class StopJPA implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Column(name = "stop_description")
private String stopDescription;
#Column(name = "id_stop", nullable = false)
private String idStop;
public StopJPA() {
}
public StopJPA(String stopDescription, String idStop) {
this.stopDescription = stopDescription;
this.idStop = idStop;
}
// .. Getters & Setters ..
}
And the Service class implementation:
StopService
#Service
final class RepoStopService {
private StopRepository stopRepository;
#Autowired
RepoStopService(StopRepository stopRepository) {
this.stopRepository = stopRepository;
}
#Transactional
public StopDTO create(StopDTO newEntry) {
StopJPA created = new StopJPA(newEntry.getStopDescription(), newEntry.getIdStop());
created = stopRepository.save(created);
return EntitiesConverter.mapEntityIntoDTO(created);
}
}
Unfortunately when i try to run it on server i get this exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'repoStopService' defined in file [C:..\RepoStopService.class]: Initialization of bean failed;
Caused by: org.springframework.aop.framework.AopConfigException:Could not generate CGLIB subclass of class [class ..RepoStopService]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class ..RepoStopService
I understand that Spring uses either JDK proxy or CGLib. The default behavior if we autowire an interface (here its the repository) is to have a JDK proxy?
what need to be changed in order to make it work?
The exception message is quite clear
AopConfigException:Could not generate CGLIB subclass of class [class ..RepoStopService
First of all it is complaining about the fact that it cannot create a proxy for your service it doesn't mention your repositories at all. Your service is a class without an interface and it is also final.
The #Transactional is on a method in your service. Spring needs to create a proxy for your service to be able to start and commit the transaction at that point. As your service isn't implementing an interface it tries to create a class based proxy, however it cannot because your class is marked final.
To fix, remove the final or create an interface to be able to use JDK Dynamic proxies instead of Cglib based class proxies.
Note: Depending on the version of Spring used, it will still fail when removing the final keyword as on earlier versions it is also required to have a no-arg default constructor and you only have a single argument constructor.
Related
I have a setup Spring + Apache CXF and I'm trying to make CustomerWebServiceImpl injectable. To do this I should inject it within #Autowired WebServiceConfig. When I do this, the WebServiceConfig doesn't even run(checked via debugger). In stack trace I see the following exception:
NoSuchBeanDefinitionException: No qualifying bean of type 'com.beginnercourse.softcomputer.domains.customer.CustomerWebService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I've checked spring annotations, everything marked with #Component/#Service. Made sure that I don't initialize any of these beans with new. Tried to replace field autowiring by setters
I have seen that there could be unexpected problems, like here
My code:
CustomerWebService
#WebService
public interface CustomerWebService {
String addCustomer(CustomerDto newCustomer);
}
CustomerWebServiceImpl
#Component
#WebService(endpointInterface = "com.soft.domains.customer.CustomerWebService")
public class CustomerWebServiceImpl implements CustomerWebService {
#Autowired
private CustomerService customerService;
#Override
public String addCustomer(CustomerDto newCustomer) {
System.out.println("Hello world");
customerService.create(new CustomerEntity());
return "Hello " + newCustomer.getName();
}
}
WebServiceConfig
#Configuration
public class WebServiceConfig {
#Autowired
private CustomerWebService customerWebService;
#Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
#Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), customerWebService);
endpoint.publish("http://localhost:8080/services/customer");
return endpoint;
}
}
UPD: I seems like only one of my configuration classes(RootConfig) is initialized fine. Others are not initializing beans. Maybe WebApplicationInitializer.onStartup expect another configuration. Then what kind of startup should be used to run new CXFServlet() with such Configuration classes?
public class WebServiceDispatcherServletInitializer implements WebApplicationInitializer {
private static final String SERVICE_DISPATCHER_SERVLET = "service_dispatcher_servlet";
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(WebServiceConfig.class, RootConfig.class, PersistenceConfig.class);
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new CXFServlet());
dispatcher.addMapping("/services/*");
}
}
I have two projects one with DAO classes and Model and another with Rest Controller
Project A : DAO Classes + Model
Project B : Rest Controller
Project A
application.properties:
spring.abcDatasource.url=
spring.abcDatasource.username=
spring.abcDatasource.password=
spring.abcDatasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.xyzDatasource.url=
spring.xyzDatasource.username=
spring.xyzDatasource.password=
spring.xyzDatasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.initialize=false
DBConfiguration.java
#Configuration
public class DBConfiguration {
#Primary
#Bean(name = "abcDS")
#ConfigurationProperties(prefix = "spring.abcDatasource")
public DataSource abcDS() {
return DataSourceBuilder.create().build();
}
#Bean(name = "abcJdbc")
public JdbcTemplate abcJdbcTemplate(#Qualifier("abcDS") DataSource abcDS) {
return new JdbcTemplate(abcDS);
}
#Bean(name = "xyzDS")
#ConfigurationProperties(prefix = "spring.xyzDatasource")
public DataSource xyzDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "xyzJdbc")
public JdbcTemplate ebsJdbcTemplate(#Qualifier("xyzDS") DataSource xyzDatasource) {
return new JdbcTemplate(xyzDatasource);
}
}
AlphaDAO.Java
#Repository
public class AlphaDAO{
#Autowired
#Qualifier("abcJdbc")
private JdbcTemplate abcJdbc;
#Autowired
#Qualifier("xyzJdbc")
private JdbcTemplate xyzJdbc;
SqlParameterSource namedParameters;
public Collection<Alpha> findAll(String owner){
String sql = "SELECT * from alpha where OWNER in (:owner)" ;
NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(abcJdbc.getDataSource());
namedParameters = new MapSqlParameterSource("owner", owner);
List<Alpha> list = namedParameterJdbcTemplate.query(sql,namedParameters,
new BeanPropertyRowMapper(Alpha.class));
return list;
}
Project B Rest Controller :
AlphaServiceApplication.java
#SpringBootApplication
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class AlphaServiceApplication extends SpringBootServletInitializer implements WebApplicationInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(AlphaServiceApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(AlphaServiceApplication.class, args);
}
}
AlphaServiceController.java
#RestController
public class AlphaServiceController {
private static final Logger logger = LoggerFactory.getLogger(AlphaServiceController.class);
#Autowired
AlphaDAO dao;
#CrossOrigin(origins = "http://localhost:4200")
#RequestMapping("/alpha")
public Collection<Alpha> index(#RequestBody String owner) {
return dao.findAll(owner);
}
If I try to run the rest controller I am getting the error saying
APPLICATION FAILED TO START
Description:
Field dao in com.xyz.web.wip.AlphaService.AlphaServiceController required a bean of type 'com.xyz.comp.wip.alphaComp.dao.AlphaDAO' that could not be found.
Action:
Consider defining a bean of type 'com.xyz.comp.wip.alphaComp.dao.AlphaDAO' in your configuration.
Your AlphaDao class doesnt make much sense, you are trying to autowire two fields but you still have a constructor.
Spring cant build the object because there is no qualifier on the constructor.
You can either do constructor injection or field injection but you shouldn’t use both.
I would recommend using constructor injection.
#Repository
public class AlphaDAO{
private final JdbcTemplate abcJdbc;
private final JdbcTemplate xyzJdbc;
#Autowired
public AlphaDAO(
#Qualifier("abcJdbc") JdbcTemplate abcJdbc,
#Qualifier("xyzJdbc") JdbcTemplate xyzJdbc){
this.abcJdbc = abcJdbc;
this.xyzJdbc = xyzJdbc;
}
Also remove your #Bean method from the controller.
Since the DAO classes and Rest Controller is in different packages. Added scanBasePackages to #SpringBootApplication annotation with one level up worked fine.
AlphaServiceApplication.java
#SpringBootApplication(scanBasePackages = { "com.xyz" })
I have a Spring service which is checking database entries. To minimize my repository calls both find methods are "#Cacheable". But when I try to init my service bean while my configuration class has a CacheManager bean definition I get following NoSuchBeanDefinitionException:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'foo.mediacode.directory.MediaCodeDirectoryService' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:353)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1093)
at foo.mediacode.directory.MediaCodeDirectoryService.implementation(MediaCodeDirectoryService.java:63)
at foo.campaigntree.directory.CampaignTreeDirectoryService.<init>(CampaignTreeDirectoryService.java:18)
... 15 more
If I take out the CacheManager bean definition, I can init my service bean and it runs without any problems and caching!
Here is my code:
Configuration
...
#Configuration
#EnableCaching
#EnableJpaRepositories(...)
#PropertySource({...})
public class MediaCodeDirectoryServiceConfig {
private static Logger configLogger = Logger.getLogger(MediaCodeDirectoryServiceConfig.class.getName());
#Value("${jpa.loggingLevel:FINE}")
private String loggingLevel;
#Value("${mysql.databaseDriver}")
private String dataBaseDriver;
#Value("${mysql.username}")
private String username;
#Value("${mysql.password}")
private String password;
#Value("${mysql.databaseUrl}")
private String databaseUrl;
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
...
}
#Bean
public MediaCodeDirectoryService mediaCodeDirectoryService() {
return new MediaCodeDirectoryService();
}
#Bean
public CacheManager mediaCodeCacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("mediaCodeMappingRegexCache"),
new ConcurrentMapCache("mediaCodeMappingsCache")));
return cacheManager;
}
#Bean
public JpaTransactionManager transactionManager() {
...
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
...
}
public DataSource getDataSource() {
...
}
public JpaDialect getJpaDialect() {
...
}
public Properties getEclipseLinkProperty() {
...
}
public JpaVendorAdapter getJpaVendorAdapter() {
...
}
}
Service
....
public class MediaCodeDirectoryService implements MediaCodeDirectoryServiceApi {
...
#Autowired
private MediaCodeDirectoryRepository repo;
#SuppressWarnings("resource")
public static MediaCodeDirectoryServiceApi implementation() {
if (INSTANCE == null) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MediaCodeDirectoryServiceConfig.class);
INSTANCE = ctx.getBean(MediaCodeDirectoryService.class);
}
return INSTANCE;
}
...
Repository
...
#Repository
public interface MediaCodeDirectoryRepository extends CrudRepository<MediaCodeDao, Integer> {
#Cacheable("mediaCodeMappingRegexes")
#Query("SELECT m FROM #{#entityName} m WHERE (m.fooId = :fooId) AND (m.isRegex = :isRegex) ORDER BY (m.orderId DESC, m.id ASC)")
List<MediaCodeDao> findByfooIdAndIsRegexOrderByOrderIdDescAndIdAsc(#Param("fooId") int fooId, #Param("isRegex") boolean isRegex);
#Cacheable("mediaCodeMappings")
List<MediaCodeDao> findByMediaCode(String MediaCode, Pageable pageable);
}
When I debug into DefaultListableBeanFactory I can find within beanDefinitionMap my mediaCodeDirectoryService and also within beanDefinitionNames mediaCodeDirectoryService appears. But DefaultListableBeanFactory.getBean(...) cannot resolve name and namedBean in line 364 is null.
When I try to get the context via String like:
INSTANCE = (MediaCodeDirectoryService) ctx.getBean("mediaCodeDirecotryService")
I avoid the NoSuchBeanDefinitionException but I run into an other one.
Anybody here has an idea on what might be the cause of this? Did I missed something in my configuration? Thx!
Caching is applied through AOP. For AOP Spring uses a proxy based approach and the default is to create interface based proxies.
public class MediaCodeDirectoryService implements MediaCodeDirectoryServiceApi {... }
With this class definition at runtime you will get a dynamically created class (Proxy$51 or something along those lines) which implements all interfaces but it isn't a MediaCodeDirectoryService. It is however a MediaCodeDirectoryServiceApi.
You have 2 ways of fixing this, either program to interfaces (which you should have been doing anyway because you have defined interfaces) instead of concrete classes or use class based proxies.
The first option involves you changing your code in the places the directly #Autowire or get an instance of MediaCodeDirectoryService to use MediaCodeDirectoryServiceApi instead (which imho you should already do, why else define an interface). Now you will get the proxy injected and everything will work.
The second option involves you setting proxyTargetClass=true on your #EnableCaching annotation. Then instead of an interface based proxy you will get a class based proxy.
#EnableCaching(proxyTargetClass=true)
I'm trying to excute the following test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = DBDataManipulatorServiceTestContext.class, loader =
SpringApplicationContextLoader.class)
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class UserInterfaceBeanTest {
#Autowired
private DBDataManipulatorService dbDataManipulatorService;
.....
#Test
public void testGetDistinctWorkPackageId() {
WorkPackage workPackage1 = new WorkPackage();
workPackage1.setWorkPackageId("TEST1");
workPackage1.setWorkPackageName("WP_1");
WorkPackage workPackage2 = new WorkPackage();
workPackage2.setWorkPackageId("TEST2");
workPackage2.setWorkPackageName("WP_2");
WorkPackage workPackage3 = new WorkPackage();
workPackage3.setWorkPackageId("TEST3");
workPackage3.setWorkPackageName("WP_3");
WorkPackage workPackage4 = new WorkPackage();
workPackage4.setWorkPackageId("TEST4");
workPackage4.setWorkPackageName("WP_4");
Aircraft aircraft1 = new Aircraft();
aircraft1.setAircraftId(50001);
aircraft1.setModel("100");
Aircraft aircraft2 = new Aircraft();
aircraft2.setAircraftId(50002);
aircraft2.setModel("100");
aircraft1.addOrUpdateWorkPackageToAircraft(workPackage1);
aircraft1.addOrUpdateWorkPackageToAircraft(workPackage3);
aircraft2.addOrUpdateWorkPackageToAircraft(workPackage2);
aircraft2.addOrUpdateWorkPackageToAircraft(workPackage3);
Map<Integer, Aircraft> aircraftsMap = new HashMap<Integer, Aircraft>();
aircraftsMap.put(50001, aircraft1);
aircraftsMap.put(50002, aircraft2);
UserInterfaceBean userInterfaceBean = new UserInterfaceBean();
userInterfaceBean.setModel("100");
aircraftsMap = dbDataManipulatorService.saveToDataBase(aircraftsMap);
List<String> workPackgesIds = userInterfaceBean.getDistinctWorkPackageId();
assertTrue(workPackgesIds.contains("TEST1"));
assertTrue(workPackgesIds.contains("TEST2"));
assertTrue(workPackgesIds.contains("TEST3"));
assertTrue(!workPackgesIds.contains("TEST4"));
}
But I get NullPointerException due to dbDataManipulatorService that is not correctly injected, my serviceContext is the following:
#ComponentScan
#EnableAutoConfiguration
#EnableBatchProcessing
#EnableJpaRepositories
public class DBDataManipulatorServiceContext {
.....
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().setName("aircraft").setType(H2)
.build();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean lef = new
LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource);
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com");
return lef;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter =
new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(true);
hibernateJpaVendorAdapter.setGenerateDdl(true);
hibernateJpaVendorAdapter.setDatabase(Database.H2);
return hibernateJpaVendorAdapter;
}
.....
Can anyone tell me where is the problem? and how to solve it.
EDIT
Here's my DBDataManipulatorServiceImpl:
#Service
#Transactional
public class DBDataManipulatorServiceImpl implements DBDataManipulatorService {
.....
}
And here's it's interface:
public interface DBDataManipulatorService {
public AircraftRepository getAircraftRepository();
public Aircraft getAircraftById(String id);
public Map<Integer, Aircraft> saveToDataBase(Map<Integer, Aircraft> aircrafts);
public MyJob findJobByJobId(String jobId);
public WorkPackage findWorkPackageByAircraftIdAndWorkPackageId
(int aircraftId, String workPackageId);
public Aircraft findAircraftByaircraftId(int aircraftId);
public List<Aircraft> findAllAircrafts();
public List<String> findAllAvailableAircraftsModels();
public List<Aircraft> findAllAircraftsByModel(String model);
public List<WorkPackage> getWorkPackagesByAircraftModel(String model);
}
You have a #ComponentScan but you have not put the name of the package to scan from. The default behavior is to scan from the package where you have put the #ComponentScan essentially the package of your DBDataManipulatorServiceContext config class. I am guessing this is not where your DBDataManipulatorService is, if so just specify a package name to your #ComponentScan
The #Autowired annotation by default means that a bean must have been found otherwise you would have gotten a bean not found exception.
There are a few things that can cause this:
The unit test is instantiated via new DBDataManipulatorServiceContext()instead of being scanned as a Spring Bean, in this case #Autowired is ignored.
There is some XML configuration that overrides the annotations configuration, and so the bean is first created with autowiring on, and then later is discarded by a bean defined in XML with no parameter provided for the missing property
You need to mark the DBDataManipulatorService class somehow. Use #service or #component annotation over class name. This will tell spring to manage the class and thus to inject it in your test.
I try to implement using Spring 3.1.0.RELEASE + Hibernate to make RESTful web service followed this guy's project https://github.com/eugenp/REST
when I run my project is contain error like this.
SEVERE: Context initialization failed
*.BeanCreationException: Error creating bean with name 'userServiceController': Injection of autowired dependencies failed;
*.BeanCreationException: Error creating bean with name 'defaultUserService': Injection of autowired dependencies failed;
*.BeanCreationException: Could not autowire field: private com.cloudlb.dao.UserDAO com.cloudlb.service.DefaultUserService.userDao;
*.NoSuchBeanDefinitionException: No matching bean of type [com.cloudlb.dao.UserDAO]
This is my configuration: (persistence.properties)
ApplicationConfig:
#Configuration
#ComponentScan(basePackages = "com.cloudlb", excludeFilters = { #ComponentScan.Filter(Configuration.class)})
public class ApplicationConfig {
#Bean
public static PropertyPlaceholderConfigurer properties() {
final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
final Resource[] resources = new ClassPathResource[]{new ClassPathResource("persistence.properties"), new ClassPathResource("restful.properties")};
ppc.setLocations(resources);
ppc.setIgnoreUnresolvablePlaceholders(true);
return ppc;
}
In PersistenceHibernateConfig contain like this:
#Profile("hibernate")
#EnableTransactionManagement
public class PersistenceHibernateConfig { ...
#Bean
public LocalSessionFactoryBean alertsSessionFactoryBean() { ...
#Bean
public DataSource restDataSource() { ...
#Bean
public HibernateTransactionManager transactionManager() { ...
WebConfig:
#Configuration
#EnableWebMvc
public class WebConfig { ... }
So, it start get an error in autowired from here:
UserServiceController:
#Controller
public class UserServiceController {
#Autowired
private UserService userService;
UserService which is implemented by DefaultUserService:
#Service
#Transactional(propagation = Propagation.REQUIRED)
public class DefaultUserService implements UserService {
#Autowired
private UserDAO userDao;
UserDAO:
public interface UserDAO extends GenericDAO<User> { ... }
UserHibernateDAO:
#Profile("hibernate")
public class UserHibernateDAO extends GenericHibernateDAO<User> implements UserDAO{ ... }
GenericHibernateDAO:
#Profile("hibernate")
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class GenericHibernateDAO<T extends Serializable> extends AbstractHibernateDAO<T> implements GenericDAO<T> { ... }
And last one AbstractHibernateDAO:
#Transactional( propagation = Propagation.SUPPORTS )
public abstract class AbstractHibernateDAO<T extends Serializable> implements DAO<T> {
private Class<T> clazz;
#Autowired
private SessionFactory sessionFactory;
public AbstractHibernateDAO() {
super();
}
public final void setClazz(final Class<T> clazz) {
this.clazz = clazz;
}
#Override
#Transactional( readOnly = true )
public T findById(String id) {
return (T) this.getCurrentSession().get(this.clazz, id);
}
protected Session getCurrentSession() {
return this.sessionFactory.getCurrentSession();
}
}
I thought it could find UserHibernateDAO. May be I missing something here. So, hope someone know how to fix it. I struck at this problem for 2 day.
I guess there could be a problem in SessionFactory too. Because I start to fix that thing and this came up.
Thank you in advance.
In addition to #Profile("hibernate") the UserHibernateDAO needs an annotation declaring it a Spring bean like #Named or #Component.