Getting UnsatisfiedDependencyException intermittently for repository - spring-boot

In my project I have created a repository interface by implementing CrudRepository. My underlying DB is Cassandra. I am intermittently getting below error and my application is failing to start -
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userHelper': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.org.retail.userops.repository.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
There are other repository interfaces which are working fine.
My spring boot app -
#SpringBootApplication
#Configuration
#ComponentScan( basePackages = "com.org.retail")
#EnableCassandraRepositories( basePackages = { "com.org.retail.userops.repository" })
public class UserApplication {
/**
* The main method.
*
* #param args
* the arguments
*/
public static void main( String[] args) {
SpringApplication.run(UserApplication.class, args);
}
/**
* Rest template.
*
* #param builder
* the builder
* #return the rest template
*/
#Bean
public RestTemplate restTemplate( RestTemplateBuilder builder) {
return builder.build();
}
}
This is UserRepository interface -
package com.org.retail.userops.repository;
import java.util.List;
import org.springframework.data.cassandra.repository.Query;
import org.springframework.data.repository.CrudRepository;
import com.org.retail.userops.domain.User;
public interface UserRepository extends CrudRepository<User, String> {
#Query( "select * from user where userid=?0 and userstatus IN (?1)")
List<User> findByUserIdAndUserStatus( String userId, List<String> statusList);
}
Sometimes application is getting up and sometimes not, so its weird. I am suspecting if there is any Cassandra error while loading repository. Is there any way to see sql errors in startup in spring boot?

Add #Repository (or #Service or #Component) on top of UserRepository class, It might fix the issue.
But if the issue is only intermittent, then there might be some connectivity issues with cassandra DB from you local machine.
To see what queries are going, add these in application.properties file
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
logging.level.org.hibernate.type=TRACE
To see what spring is doing behind the scenes or at startup, add this:
logging.level.org.springframework=DEBUG

Related

Error with using #ComponentScan on multiple packages in Spring Boot

Here's my issue--I have a service that relies on an external library. I was trying to autowire the service so I can use it but was not able to
import org.keycloak.admin.client.token.TokenService;
public class SimpleService {
#Autowired
private TokenService keycloakTokenSvc; // Could not autowire, no beans of type 'TokenService' found
public void execute() {
keyCloakTokenSvc.doSomething();
}
}
I then added this to my SpringBootApplication and got it working:
#SpringBootApplication
#ComponentScan({"org.keycloak.admin.client.token"})
public MyApp {}
Sweet -- all good now, right? Nope. It seems like this overrides some of my auto configuraitons like my security config, so I was no longer to make RESTful requests to my application while it was running. I then did this next:
#SpringBootApplication
#ComponentScan({"org.keycloak.admin.client.token", "com.project.pkg"})
public MyApp {}
Still nothing. I get the same error as before:
Field keycloakTokenSvc in com.mark43.jms.services.TokenRefreshService required a bean of type 'org.keycloak.admin.client.token.TokenService' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'org.keycloak.admin.client.token.TokenService' in your configuration.
I'm new to Spring Boot so not sure what to do here. Is there a way to use the TokenService without Autowiring? Is there a way to scan both packages?
It seems to me that you need to create a TokenService bean as follows:
#Configuration
public class TokenConfig {
#Bean
public TokenService tokenService() {
return new TokenService(); // Or whatever you need to instantiate it
}
}
This will register a TokenService object as a Spring-managed bean so that it can be autowired into SimpleService.

No qualifying bean of type repository when running test but not main application

I'm developing a Spring Boot application following TDD methodology. I've created the main classes (controller, service and repository) this way:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class CrimeServiceImpl implements CrimeService{
#Autowired
private CrimeRepository repository;
...
Controller:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class CrimeController {
#Autowired
private CrimeServiceImpl service = new CrimeServiceImpl();
Repository:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface CrimeRepository extends JpaRepository<Crime, Long>{
}
This is the project structure:
If I run the application normally, no error. The classes' methods are empty. Then I've created a test class like this:
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = CrimeServiceImpl.class)
#ComponentScan("com.springmiddleware")
#AutoConfigureMockMvc
#SpringBootTest
public class TestCrimeService {
//Calling method getAllCrimes works
#Test
public void returnAllCrimesExists() throws NoSuchMethodException, SecurityException {
List<Crime> list = new ArrayList<>();
assertTrue(this.service.getAllCrimes() == list);
}
And if I run this, the following error is shown and the test fails:
NoSuchBeanDefinitionException: No qualifying bean of type 'com.springmiddleware.repository.CrimeRepository' available: expected at least 1 bean which qualifies as autowire candidate.
I've checked all annotations and it seems to me that all is ok, and I thought if I missed something, even in the normal run the application would fail. What did I got wrong?
I wanted also to make a test class for a JPARepository, and I also encountered the same error message:
NoSuchBeanDefinitionException: No qualifying bean of type
'SomethingRepository' available:
expected at least 1 bean which qualifies as autowire candidate.
I could make it work by adding the 2 following annotations on top of the test class:
#EnableJpaRepositories(basePackageClasses = SomethingRepository.class) // repository
#EntityScan(basePackageClasses = Something.class) // entity of the repository
Now it looks like:
#RunWith(SpringRunner.class)
#EnableJpaRepositories(basePackageClasses = SomethingRepository.class) // repository
#EntityScan(basePackageClasses = Something.class) // entity of the repository
#SpringBootTest(classes = MyDbUnitTestApp.class) // does some #ComponentScan and #EntityScan on the repositories/entities package, and #EnableAutoConfiguration
#ActiveProfiles(Profiles.myTestProfile)
#DatabaseSetup(value = {
"/datasets/dataset1.xml" }, type = DatabaseOperation.CLEAN_INSERT)
public class SomethingRepositoryTest {
#Autowired
private SomethingRepository sut;
#Test
public void findById() {
Something something= sut.findById(1L);
Assert.assertEquals("foobar", something.getName());
}
}

Test application cannot find autowired bean in same project

I have a jar file that is the persistence layer, ad I just want to test the DAO that are simply autowired into other service layer clasees. But I want to test without any mocking or whatever.
I think this should be pretty simple. I have this in my srs/test/java
#RunWith(SpringRunner.class)
#ComponentScan("com.xxxx")
public class ApplicationTester {
#Autowired
AplicationDocumentDao aplicationDocumentDao;
#Test
private void testAplicationDocumentDao() {
aplicationDocumentDao.allForOrg(1);
}
}
All the DAO's are in the same projust under the usual /src/main/java
When I run the mvn to just run the tests like this:
mvn -Dtest=ApplicationTester test
I get this error:
Error creating bean with name 'xxx.test.ApplicationTester': Unsatisfied dependency expressed through field 'aplicationDocumentDao';
nested exception is 0rg.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'xxx.dao.AplicationDocumentDao' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Which means is can't find the Bean of course, but i would think the #ComponentScan would pick up add the Dao's.
How do I get this tester to find all my Dao's (Which are all annotated with #Componenet) and are picked up just fine in the rest for the application.
Any ideas?
** EDIT **
here is the DAO
#Repository
#Component
public class AplicationDocumentDao extends JdbcDaoSupport {
#Autowired
public void setJT(JdbcTemplate jdbcTemplate) {
setJdbcTemplate(jdbcTemplate);
}
public List<ApplicationDocumentBean> allForOrg(int orgId) {
String sql = "SELECT * FROM ApplicationDocument WHERE organizationId = ?";
return (List<ApplicationDocumentBean>) getJdbcTemplate().query(sql, new BeanPropertyRowMapper<ApplicationDocumentBean>(ApplicationDocumentBean.class), orgId);
}
}
Add annotate to your persistence layer class, for example: #Repository or #Component,like this :
#Repository
public interface OrderMapper {}

spring data JPA & spring data elasticsearch; No property index found for type?

I'm unsure why this is happening! I've got a class that is used by spring data elasticsearch and spring data jpa, but when I try run my application I get an error.
Error creating bean with name 'articleSearch':
Invocation of init method failed; nested exception is
org.springframework.data.mapping.PropertyReferenceException:
No property index found for type Article!
Caused by: org.springframework.data.mapping.PropertyReferenceException:
No property index found for type Article!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77) ~[spring-data-commons-1.11.4.RELEASE.jar:na]
I've got the following application class:
#SpringBootApplication
#EnableAsync
#ComponentScan(basePackages = {"com.article.models", "com.user"})
public class ArticleApplication {
And the following elasticsearch config:
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.article.search")
public class ElasticSearchConfiguration {
#Resource
private Environment environment;
#Bean
public Client client() {
TransportClient client = new TransportClient();
TransportAddress address = new InetSocketTransportAddress(environment.getProperty("elasticsearch.host"), Integer.parseInt(environment.getProperty("elasticsearch.port")));
client.addTransportAddress(address);
return client;
}
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(client());
}
}
This is how I've setup my model class:
#Entity
#Table(name="article")
#Document(indexName="article", type="articles")
public class Article implements Serializable {
I've then got a package search that extends the elasticsearchrepository, like so:
public interface ArticleSearch extends ElasticsearchRepository<Article, String> {
I'm trying to autowire the articlesearch class inside another service which is causing the error to occur:
#Autowired
ArticleSearch articleSearch;
What am I missing here?! I guess it's a bit more complex when trying to use data-jpa + data-elasticsearch.
I found out why this was happening. I'm not sure why, but spring didn't seem to be picking up my ElasticSearchConfiguration configuration class!
So I simply moved all the contents from that and dumped it in my main application class (where all my other config is).
I also removed component scan & added the enablejparepository + enableelasticsearchrepository annotations to my main class. Here is what it looks like now:
#SpringBootApplication
#EnableAsync
#EnableElasticsearchRepositories(basePackages = "com.article.search")
#EnableJpaRepositories(basePackages = {"com.article.dao", "com.user.dao"})
public class ArticleApplication {

How to create a google Oauth in spring?

I'm new to spring so bear with me :o
I'm using Spring Boot v1.1.8.RELEASE
I'm trying to get a working google Oauth connection with my website.
So I'm trying to get the spring-social-google working while the twitter & facebook one are working.
I read this http://gabiaxel.github.io/spring-social-google-reference/overview.html
I read the tutorial from Spring.io for the other providers(twitter & Facebook).
So here is the code I have :
package app.controllers;
import javax.inject.Inject;
import org.springframework.social.google.api.Google;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
#RequestMapping("/google")
public class GoogleController {
private Google google;
#Inject
public GoogleController(Google google) {
this.google = google;
}
/**
*
* #param model
* #return
*/
#RequestMapping(method = RequestMethod.GET)
public String helloGoogle(Model model) {
if (!google.isAuthorized()) {
return "redirect:/connect/google";
}
model.addAttribute(google.plusOperations().getGoogleProfile());
return "testGoogle";
}
}
I have the files like for facebook in my templates a
googleConnect.html and a googleConnected.html.
Maven is importing correctly the dependencies
The application.properties have the secret and appid from a google
App I created
Here is the error I have :
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'googleController' defined in file [C:\Users\Antoine\Documents\NetBeansProjects\p0907931-cinemagik\app\target\classes\app\controllers\GoogleController.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.social.google.api.Google]: : No qualifying bean of type [org.springframework.social.google.api.Google] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.social.google.api.Google] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
The bean should be autowired like the other providers right ?
Thanks for your time.
edit :
This bean is working but I don't know how to implement it in my controller ?
#Configuration
public class SocialConfig {
#Inject
private Environment environment;
#Bean
public ConnectionFactoryLocator connectionFactoryLocator() {
ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
registry.addConnectionFactory(new GoogleConnectionFactory(
environment.getProperty("superAPI"),
environment.getProperty("superSecret")));
return registry;
}
}
Spring Boot only has autoconfig support for Spring Social with Twitter, Facebook and LinkedIn (not Google). You can probably copy the code from the existing implementations and adapt it: https://github.com/spring-projects/spring-boot/tree/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social.
package app.controllers;
import javax.inject.Inject;
import org.springframework.social.google.api.Google;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class GoogleController {
private Google google;
#Inject
public GoogleController(Google google) {
this.google = google;
}
/**
*
* #param model
* #return
*/
#RequestMapping(method = RequestMethod.GET,value="/google")
public String helloGoogle(Model model) {
if (!google.isAuthorized()) {
return "redirect:/connect/google";
}
model.addAttribute(google.plusOperations().getGoogleProfile());
return "testGoogle";
}
}

Resources