I have a projected checked into GitHub here
https://github.com/romeoopk/demo
Please note that this is not a "complete" working project but in progress!
I have two data sources (h2 mem DB and Cassandra)
The aim of the project is to hide the implementation behind the Service.
there are two profiles I am looking against
dev - goes against h2
test - goes against Cassandra
when I run against test, it runs fine as expected but when I run against dev, I get the following message
Parameter 0 of constructor in com.example.demo.service.H2HotelServiceImpl required a bean of type 'com.example.demo.repository.HotelRepository' that could not be found.
Action:
Consider defining a bean of type 'com.example.demo.repository.HotelRepository' in your configuration.
I am unsure, how to have a proper injection so that the H2HotelRepository and H2HotelByLetterRepository get used for querying towards H2
any help is highly appreciated!!!
Your repository classes under cassandra folder is like this
#Repository
#Profile("test")
public class CassandraHotelRepository implements HotelRepository<Hotel> {
....
}
#Repository
#Profile("test")
public class CassandraHotelByLetterRepository implements HotelByLetterRepository<HotelByLetter, HotelByLetterKey> {
....
}
But in your h2 folder you have declared as
#Repository
#Profile("dev")
public abstract class H2HotelRepository implements CrudRepository<Hotel, String>, HotelRepository<Hotel> {
...
}
#Repository
#Profile("dev")
public abstract class H2HotelByLetterRepository implements CrudRepository<HotelByLetter, HotelByLetterKey>, HotelByLetterRepository<HotelByLetter, HotelByLetterKey> {
.....
}
As you can clearly see in h2 folder i.e. for profile dev, there is no concrete class. Both of your repositories under h2 are abstract.
Remove abstract and it should work fine.
Related
I've got a fairly standard spring boot app which is built with gradle from several gradle modules. Here's the directory layout:
- root
- serviceA
- src/main/java
- org.example.serviceA
- ServiceAApplication.java
- serviceB
- serviceC
- common
- src/main/java
- org.example.common
- CommonSecurityConfiguration.java
What I would like to do is to include the CommonSecurityConfiguration class from the shared common module in serviceA. Note that ServiceAApplication and CommonSecurityConfiguration reside in different base packages.
I tried to use #Import(CommonSecurityConfiguration.class) on my ServiceAApplication, but that had no observable effect at all.
The only thing which worked was to annotate ServiceAApplication like so:
#SpringBootApplication(basePackages = { "org.example.serviceA", "org.example.common"})
public class ServiceAApplication { ... }
This approach works, but seems very coarse grained to me - it will import each and every component and configuration it finds in org.example.common.
Is there a better way to do this? Can I include individual classes into the component scan by listing them one by one?
Try to use
#Import(CommonSecurityConfiguration.class) above configuration class. So it would look like this:
#Configuration
#Import(CommonSecurityConfiguration.class)
public class ServiceAConfiguration { ... }
I believe what you are looking for is #CompnentScan("com.example"), this will tell Spring to look at all the files under the specified path recursively. (In this case it would be #ComponentScan("root"))
You find more info here: baeldun.com/spring-component-scanning
Hope this helps.
Since you want to control which components are brought in , we can make an annotation , let's call that annotation PickyComponentImport
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface PickyComponentImport{
}
Then on our SpringBootApplication annotation we can add a new filter which looks for this annotation.
#ComponentScan(basePackages = { "org.example.serviceA",
"org.example.common" }, includeFilters = #Filter(PickyComponentImport.class))
public class ServiceAApplication { ... }
Then we can just add that annotation on any class we want included
#Configuration
#PickyComponentImport
public class CommonSecurityConfiguration {
}
EDIT: I think if you go with this approach you can just componentScan basepackage as root.
New to spring boot.
We have reusable beans in multiple base dependencies. Since, we need those reusable functionality, we are inheriting those jars in pom.xml.
Ex:
Jar1:
ClassName: UserInfo, RequestInterceptors, ClassName3, ClassName4, ClassNameN.
PackageName: com.somename1.base.comps
Jar2:
ClassName: UserInfo, RequestInterceptors, ClassName3, ClassName4, ClassNameN.
PackageName: com.somename2.base.comps
Since the class name is similar, creates conflict issue, when building.
Unfortunatly, we cannot able to change any class names, since someother teams are using these jar. No permission to create another version of these jars.
Is there any way to include both jar without excluding these conflicting components in #EnableAutoConfiguration or #ComponentScan
annotations?
Could someone share some advice here.
The solution here would be to name your beans. The reason for the conflict would be that the names of the classes are the same. For example:
#Configuration
public class Config{
public com.somename2.base.comps.UserInfo somename2UserInfo(){
return new com.somename2.base.comps.UserInfo();
}
public com.somename1.base.comps.UserInfo somename1UserInfo(){
return new com.somename1.base.comps.UserInfo();
}
}
The beans would then be named somename1UserInfo and somename2UserInfo and you can use these names instead when autowiring, e.g.:
public class SomeImpl{
#Autowired
#Qualifier("somename1UserInfo")
UserInfo userInfo;
/*
* Or you can do this
*/
#Resource(name = "somename1UserInfo")
UserInfo theSameUserInfo
}
This will allow you to autowire whichever bean should be used in whichever class. It may not be ideal to have to declare a qualifier for every place the classes are used, so if one implementation is primarily used, consider looking into the #Primary annotation.
I'm trying to implement a custom Spring repository. I have the interface:
public interface FilterRepositoryCustom {
List<User> filterBy(String role);
}
the implementation:
public class FilterRepositoryImpl implements FilterRepositoryCustom {
...
}
and the "main" repository, extending my custom repository:
public interface UserRepository extends JpaRepository<User, String>, FilterRepositoryCustom {
...
}
I'm using Spring Boot and, according to the docs:
By default, Spring Boot will enable JPA repository support and look in
the package (and its subpackages) where #SpringBootApplication is
located.
When I run my application, I get this error:
org.springframework.data.mapping.PropertyReferenceException: No property filterBy found for type User!
The problem here is that you are creating FilterRepositoryImpl but you are using it in UserRepository. You need to create UserRepositoryImpl to make this work.
Read this doc for more detail
Basically
public interface UserRepositoryCustom {
List<User> filterBy(String role);
}
public class UserRepositoryImpl implements UserRepositoryCustom {
...
}
public interface UserRepository extends JpaRepository<User, String>, UserRepositoryCustom {
...
}
Spring Data 2.x update
This answer was written for Spring 1.x. As Matt Forsythe pointed out, the naming expectations changed with Spring Data 2.0. The implementation changed from the-final-repository-interface-name-with-an-additional-Impl-suffix to the-custom-interface-name-with-an-additional-Impl-suffix.
So in this case, the name of the implementation would be: UserRepositoryCustomImpl.
Another way this error can happen if the impl class for FilterRepositoryCustom isn't picked up in your spring configuration:
#EnableJpaRepositories(basePackageClasses = {RepoPackageMarker.class, FilterRepositoryCustomImpl.class})
I had the same problem. Please check if your packages structure looks like this
custom
impl
- FilterRepositoryCustomImpl.class
- FilterRepositoryCustom.class
Because when I try to use my custom repo it doesn't see the implementation. (implementation should be in the same package or in sub-packages for Spring to see it)
Maybe it helps somebody (ノ^∇^)
Is it a must that the customMethod() in the CustomRepository can only have parameters defined that are either
1.Entity class name - customMethod(User user),
2.Entity class attributes - customMethod(String firstName), here firstName is an attribute of User Entity class.
Can I not have something like customMethod(CustomCriteria criteria), the criteria class contain the various attributes that are used to construct a dynamic query.
e.g. getStatusByCriteria(CustomCriteria criteria), CustomCriteria is a simple pojo annotated with #Component so that spring identifies it.
When I tried this I get an error:
org.springframework.data.mapping.PropertyReferenceException: No
property criteria found for type UserRepository!
for me the keys was
#EnableJpaRepositories(repositoryBaseClass = MyRepositoryImpl.class)
#NoRepositoryBean annotation on interface
follow the docs for your spring ver
https://docs.spring.io/spring-data/data-commons/docs/2.3.4.RELEASE/reference/html/#repositories
so as result i have:
#NoRepositoryBean
public interface SliceRepository<T, ID> extends JpaRepository<T, ID> {..}
public class SliceRepositoryImpl<T, ID> extends SimpleJpaRepository<T, ID> implements SliceRepository<T, ID> {..}
#EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactory",
basePackages = {"com.some.servicename.repository"},
repositoryBaseClass = SliceRepositoryImpl.class
)
I also had this error. It occured because I had configured elasticSearch repository with package
#EnableElasticsearchRepositories("some.package")
Next I moved MyElasticSearchRepository from package 'some.package' to another, but didn't change configuration
I had the same problem in a project of mine. I solved the problem by adding a line in my pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<includes>
<include>com/my/package/entities/*.java</include>
<include>com/my/package/repositories/*.java</include>
<include>com/my/package/repositories/impl/*.java</include> <!-- add this -->
</includes>
</configuration>
</plugin>
The most important part of the class name that corresponds to the fragment interface is the Impl postfix.
Old way:
Entity aThing = repository.findOne(1L);
New way:
Optional<Entity> aThing = repository.findById(1L);
I'm using the spring state machine and want to add on functionality to transitions and state changes using #WithStateMachine, #OnTransition and #OnStateChanged to keep the class with #EnableStateMachine as simple as possible. I never got it to work though and after some trial and error I realised that the #WithStateMachine bean has to be created before the state machine but that dependency isn't automatically solved.
The interesting parts of my project basically boils down to the following:
package org.myorg.a
#Component
public class MyComponent {
#Autowired
StateMachine<States, Events> sm;
}
package org.myorg.b
#WithStateMachine
public class Listener {
#OnTransition
public void anyTransition() {}
}
MyComponent and therefore the state machine will be created before the Listener because Spring will look in package a before package b and in effect none of the methods in class Listener will be associated with the state machine and the anyTransition method will never be called.
The only two solutions to this that I can think of is
Rename the packages
Annotate the #EnableStateMachine class with #DependsOn and explicitly depend on all #WithStateMachine classes
In my opinion neither of those two solutions are good. Does anyone have a better way to solve this?
Hopefully this just got fixed in https://github.com/spring-projects/spring-statemachine/issues/232.
I've been looking all over Google to find some useful information on how to use Guice/Spring DI in Play Framework 2.1
What I want to do is to Inject several Services in some DAO's and vice versa.
Just need some clarification on this - With play 2.1, do you have to use an # annotation within the routes file for DI?
I've looked at this guide here - https://github.com/playframework/Play20/blob/master/documentation/manual/javaGuide/main/inject/JavaInjection.md
and applied the following steps creating a Global class in app and adding the GUICE dependencies in Build.scala but keep on getting a null pointer exception when invoking on the injected object.
Has anyone been able to get DI working in Play 2.1 using Guice? I've seen examples across the internet but they all seem to be using DI within the controller.
I noticed you are using Java. Here is how I got it to work for injecting into a controller.
First, I created the following 4 classes :
MyController:
package controllers;
import play.mvc.*;
import javax.inject.Inject;
public class MyController extends Controller {
#Inject
private MyInterface myInterface;
public Result someActionMethodThatUsesMyInterface(){
return ok(myInterface.foo());
}
}
MyInterface:
package models;
public interface MyInterface {
String foo();
}
MyImplementation2Inject:
package models;
public class MyImplementation2Inject implements MyInterface {
public String foo() {
return "Hi mom!";
}
}
MyComponentModule:
package modules;
import com.google.inject.AbstractModule;
import models.MyInterface;
import models.MyImplementation2Inject;
public class ComponentModule extends AbstractModule {
#Override
protected void configure() {
bind(MyInterface.class).
to(MyImplementation2Inject.class);
}
}
Now the final part, that took me a silly long time to figure out, was to register the module. You do this by adding the following line to the end of the application.conf file, which is located in the conf directory:
play.modules.enabled += "modules.MyComponentModule"
I hope this was helpful to you. :)
I use cake pattern and my own version of Global overriding getControllerInstance
https://github.com/benjaminparker/play-inject
Cheers
Ben
Sorry, this is a late response, but here's our example
https://github.com/typesafehub/play-guice
Have you tried using some different approach to DI than Guice?
We also tried implementing a project with Guice or Spring but ended in registering our dependencies in objects that implement trait such as:
trait Registry {
def userDao: UserDao
...
}
object Registry {
var current: Registry = _
}
object Environnment {
object Dev extends Registry {
val userDao = ...
//implement your environment for develpment here
}
object Test extends Registry {
val userDao = ...
//implement your ennviroment for tests here e.g. with mock objects
}
}
Another good approach wich might fit for you is the cake pattern (just google for it).