Spring boot: #Repository class not found to inject - spring-boot

This is my Spring boot application related code:
#ComponentScan({"net.gencat.transversal.espaidoc.scheduler", "net.gencat.transversal.espaidoc.backoffice"})
public class SchedulerApplication {//...}
By other hand, I've a repository on package net.gencat.transversal.espaidoc.backoffice.dao:
#Repository
public interface DocumentDAO extends CrudRepository<Document, String> {
}
So, I've a service with a DocumentDAO dependency:
#Service
public class DocumentServiceBackOffice {
private DocumentDAO documentDAO;
public DocumentServiceBackOffice(DocumentDAO documentDAO) {
this.documentDAO = documentDAO;
}
}
However, I'm getting this message:
NoSuchBeanDefinitionException: No qualifying bean of type 'net.gencat.transversal.espaidoc.backoffice.dao.DocumentDAO' available
I've also tried adding #EnableJpaRepositories, but it still doesn't work.
Any ideas?
EDIT
This is my SpringApplication class:
package net.gencat.transversal.espaidoc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
import net.gencat.transversal.espaidoc.common.config.FrontOfficeProperties;
import net.gencat.transversal.espaidoc.common.config.RedisConfiguration;
#SpringBootApplication(exclude = JmxAutoConfiguration.class)
#EnableConfigurationProperties({
FrontOfficeProperties.class
})
#Import(RedisConfiguration.class)
#EnableScheduling
// #ComponentScan("net.gencat.transversal.espaidoc")
//#EnableJpaRepositories
public class SchedulerApplication {
public static void main(String[] args) {
SpringApplication.run(SchedulerApplication.class, args);
}
}
EDIT2:
I've just realized on spring logs that there's some issue related with DocumentDAO:
--- [ main] .RepositoryConfigurationExtensionSupport : Spring Data JPA - Could not safely identify store assignment for repository candidate interface net.gencat.transversal.espaidoc.backoffice.dao.DocumentDAO.

Try adding the following:
#EnableJpaRepositories(basePackages="net.gencat.transversal.espaidoc.backoffice.dao")
public class SchedulerApplication

Related

spring-boot-starter-jdbc DAO repository object not injected in working legacy webservice

I am new in the spring/boot word and have a working JAX-WS based web-service declared in a springboot project. It is started and configured via web.xml and sun-jaxws.xml. So, no beans included there only endpoints declarations and servlet definitions and mappings.
I just now want to save the items i get in the webservice into the mysql database using spring-boot-starter-jdbc which is not working:
I can't achieve this as the repository is not injected in the webservice implementation.
Followed all steps in other question, but not achieving this!
Normally declaration of the datasource parameters in application.properties and annotating #webservice and #Repository would suffice to get the injection of the repository working in the webservice class. What am i missing ?
Here details of the steps I followed:
the webservice implementation is a package X and i created a #SpringBootApplication in order to use a mysql datasource declared in application.properties.
So i annotated the webservice as a #Component and the data access repository with #Repository and #Component
parent version: spring-boot-starter-parent : 1.5.10.RELEASE
webservice service implementation:
BServiceManager.java
package X;
....
#Component
#WebService(name = "***",***)
#BindingType("http://schemas.xmlsoap.org/wsdl/soap/http")
#XmlSeeAlso({
packagesxxx.class,
....
})
public class BServiceManager
implements xxxxx
{
....
#Autowired
private ItemRepository irepo;
....
#WebMethod(**)
#WebResult(***)
public ResponseDataInfo sendInfo( ){
....
trepo.saveitem(item)
....
}
}
ItemRepository.java
package Y.Z;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
#Component
#Repository
public class ItemRepository {
#Autowired
private JdbcTemplate jdbcTemplate ;
....
public boolean saveitem(Item item) {
....
}
}
Item.java
package Y.Z;
public class Item {
....
}
GetItemsApplication
package Y;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
//#ComponentScan(basePackages={"Y","Y.Z","X"})
#SpringBootApplication
public class GetItemsApplication {
....
public static void main(String[] args) {
SpringApplication.run(GetItemsApplication.class, args);
log.info("--Spring Boot inits done--");
}
}
application.properties
spring.data.jpa.repositories.enabled=false
spring.data.jdbc.repositories.enabled=true
# MySQL properties
spring.datasource.url=****
spring.datasource.username=****
spring.datasource.password=****
....
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
logging.level.org.springframework.jdbc.core.JdbcTemplate=debug
NB: even having datasource bean is not helping :
File: DataSourceConfig.java
package Y.Z;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
//#EnableJdbcRepositories for Spring
#Configuration
public class MDataSourceConfig {
#Bean
public DataSource dataSource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
return dataSourceBuilder.build();
}
#Bean
public JdbcTemplate getJdbcTemplate() {
return new JdbcTemplate(dataSource());
}
}
Your Webservice doesn't seem to get created by Spring.
Therefore Spring has no control over its dependencies, so you have to get the dependency programmatically.
There are many ways to do this.
Easy but not very elegant and uses global variables which might cause problems, especially with tests: https://stackoverflow.com/a/18486178/66686
More elegant but requires weaving Spring autowiring using #Configurable

Bean Creation or defining is failing in springboot

Main Class
package com.prac.sdp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.prac.sdp.pdf.PdfGenerator;
#SpringBootApplication
public class SdpApplication {
public static void main(String[] args) {
ApplicationContext ctx=SpringApplication.run(SdpApplication.class, args);
PdfGenerator pdg=ctx.getBean(PdfGenerator.class);
pdg.pdfgenerate();
}
}
PdfGenerator.java
package com.prac.sdp.pdf;
import java.io.FileNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
#Component
public class PdfGenerator {
#Autowired
PdfWriter writer; <------ Autowiring is not working here I don't know why.
}
Issue -- Consider defining a bean of type 'com.itextpdf.kernel.pdf.PdfWriter' in your
configuration.
Resolution tried:
Used #ComponentScan("com.itextpdf") --> Started getting Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type
'com.prac.sdp.pdf.PdfGenerator' available.
Let me know how this issue can be fixed I am stuck at this. Thanks in advance.
create bean with #Bean annotation tag , as this is from third party library , you need to define by Method.
#Bean
public PdfWriter writer(){
return new PdfWriter();
}
Add above method to your SdpApplication class.

Spring bean getting initialised twice in java configuration

I've created a spring application using spring-security with java based configuration. I've also included a jar file (created by me) in my project.
The problem I am facing is:- i have to write #ComponentScan(basePackages = {"com.mypackage"}) in both the classes (SpringConfig.java and SecurityConfig.java) which leads to initialization of beans twice.
Removing either of #componentscan leads to error:- Error creating bean with name 'securityConfig'.
Below are my java classes.
SpringConfig.java
package com.mypackage.config;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = {"com.mypackage"})
public class SpringConfig extends WebMvcConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SpringConfig.class);
#PostConstruct
public void init(){
logger.debug("Spring Config initialized");
}
}
SecurityConfig.java
package com.mypackage.config;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
#ComponentScan(basePackages = {"com.mypackage"})
public class SecurityConfig extends WebSecurityConfigurerAdapter{
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
//This Configuration class is in my jar file.
// with package starting with same name com.mypackage
#Autowired
com.mypackage.frameworks.config.Configuration config;
#PostConstruct
public void init(){
logger.debug("Security config initiaziled");
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
try {
auth.inMemoryAuthentication()
.withUser("admin").password("admin").roles("USER");
} catch (Exception e) {
e.printStackTrace();
}
}
}
MyController.java
package com.mypackage.controller;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
#Controller
public class MyController {
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
#PostConstruct
public void init(){
logger.debug("-------Controller created-------");
}
}
You have configured bean definitions into multiple #Configuration classes. My suggestion is - Aggregating #Configuration classes with #Import into single place.
Now you can able to apply #ComponentScan(basePackages = {"com.mypackage"}) in one place and context also loads bean only one time.
The #Import annotation provides just this kind of support, and it is the direct equivalent of the element found in Spring beans XML files.
Please refer this link - https://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch04s03.html
Beans will be configured and created twice because both application context scans the same package "com.mypackage". One solution is to separate SpringConfig beans package from SecurityConfig beans package. be as more specific as you can in #ComponentScan package value

spring boot #Value always null

I am using spring boot 1.5.3 and trying to inject the properties from an application-dev.properties file into a Service bean but the value is always coming as null. The value does get loaded in my DevConfiguration class though.
I have a application class as below in my base package
package com.me;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I have a configuration class as follows in
package com.me.print.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
#Configuration
#Profile("dev")
#PropertySources({
#PropertySource("classpath:application.properties"),
#PropertySource("classpath:application-dev.properties")
})
#ComponentScan(value = {"com.me.print.client"})
public class DevConfiguration {
#Value("${app.service.url}")
private String rootUri;
#Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
My Service bean that I am trying to load the value into is below
package com.me.print.client;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.me.print.model.zitResponse;
#Service
public class zitPrintClient {
private final RestTemplate restTemplate;
#Value("${app.service.url}")
private String rootUri;
public zitPrintClient(RestTemplateBuilder restTemplateBuilder) {
restTemplate = restTemplateBuilder
//.rootUri(rootUri)
.build();
}
public zitResponse getpooltatus(String poolId) {
return restTemplate.getForObject("/pool/{poolId}/#status",
zitResponse.class, poolId);
}
}
In the above class the rootURI is always null. Does anyone have any suggestions as to what I am missing
in my application-dev.properties file I have the following
app.service.url=http://localhost:8080/zitprint/v1
Thanks
UPDATE:
does anyone have any suggestions here as I tried to inject properties into my controller as follows:
#Value("${allowedVendors}") String allowedVendors
and if i put the above into a constructor it finds the value but does not find it otherwise:
public PController(#Value("${allowedVendors}") String allowedVendors) {
}
I cant use the property further in the code as with the constructor I have created two instances of the bean 1 via the constructor and the other created by spring DI. Any ideas why the value doesnt inject without the constructor
Thanks
You need to put it as a parameter in the constructor:
public zitPrintClient(RestTemplateBuilder restTemplateBuilder,
#Value("${app.service.url}") rootUri) {
this.rootUri = rootUri; // if you are only using this once,
// no need to keep this member variable around
restTemplate = restTemplateBuilder
.rootUri(rootUri)
.build();
}
The constructor gets called first when you are creating the object. The member variable, rootUri, would have it's value injected after the object is created. So, rootUri member variable would be null at the time the constructor is called.
(And, imho, for better readability, your class should start with a capital letter, i.e. ZitPrintClient, but it's your code ...)

Unable to inject dependency in Junit test

Having some trouble injecting a dependency in one of my JUnit test classes.
I believe the TestApplication is not package scanning or is not being loaded.
Code below:
package com.mitto.repositories;
import static org.junit.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.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.mitto.MittoApplicationTests;
import com.mitto.domain.User;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration( classes= { MittoApplicationTests.class } )
#TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class})
#DatabaseSetup("UserRepositoryTest.xml")
public class UserRepositoryTest {
#Autowired
UserRepository repository;
private static final long FACEBOOK_ID = 1234567;
#Test
public void getUserById() {
User user = repository.findOne(1L);
assertNotNull(user);
assertEquals( user.getFacebookId(), FACEBOOK_ID );
}
}
MittoApplicationTests.java
package com.mitto;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest
public class MittoApplicationTests {
#Test
public void contextLoads() {
}
}
UserRepository.java
package com.mitto.repositories;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import com.mitto.domain.User;
#Repository
public interface UserRepository extends PagingAndSortingRepository<User, Long>{
User findByFacebookId( long facebookId );
User findByAuthToken( String token );
}
I can't see anything wrong with this.
Sometimes, a working example is better than fixes.
Here is a working example:
First, in your configuration class
#SpringBootApplication
#ComponentScan(value = "com.mitto")
#EnableJpaRepositories(value = "com.mitto")
#EntityScan(basePackages = {"com.mitto.domain"}, basePackageClasses = {Jsr310JpaConverters.class})
public class MittoApplicationTests {
}
Second, in your test class
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = MittoApplicationTests.class) // replace the #ContextConfiguration with #SpringBootTest
// rest of of your annotations ...
public class UserRepositoryTest {
#Autowired
UserRepository repository;
// your test cases
}
A Spring Boot application is just a Spring ApplicationContext, so nothing very special has to be done to test it beyond what you would normally do with a vanilla Spring context. One thing to watch out for though is that the external properties, logging and other features of Spring Boot are only installed in the context by default if you use SpringApplication to create it.
Spring Boot provides a #SpringBootTest annotation which can be used as an alternative to the standard spring-test #ContextConfiguration annotation when you need Spring Boot features. The annotation works by creating the ApplicationContext used in your tests via SpringApplication.
Please read the documentation for more details:
SpringBootTest annotation
boot-features-testing

Resources