Spring Autowiring failing when using Cobertura - spring

When I run Cobertura, it causes the following Spring autowiring error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userResource': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.dnb.components.storage.service.UserService com.dnb.components.storage.rest.resource.UserResource.userService; nested exception is java.lang.IllegalArgumentException: Can not set com.dnb.components.storage.service.UserService field com.dnb.components.storage.rest.resource.UserResource.userService to com.sun.proxy.$Proxy56 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
As suggested in other related posts, I tried forcing Spring to use CGLIB by changing "proxyTargetClass=true", but this results in a different error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userResource': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.dnb.components.storage.service.UserService com.dnb.components.storage.rest.resource.UserResource.userService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.dnb.components.storage.repository.UserRepository com.dnb.components.storage.service.UserService.repository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Post-processing of the FactoryBean's object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy54]: 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 com.sun.proxy.$Proxy54
This is what the Repository class looks like:
#Transactional
public interface UserRepository extends CrudRepository<User, Long> {
public User findByCrmId(String crmIdId);
}
Here is the service that gets injected with UserRepository:
#Service
#Transactional
public class UserService extends TraceablePersistenceService<User, UserRepository> {
#Autowired
UserRepository repository;
#Transactional
public Iterable<User> findAll() {
return repository.findAll();
}
public User findOne(Long id) {
return repository.findOne(id);
}
}
Our configuration is in
#Configuration
#EnableTransactionManagement(proxyTargetClass=true)
#EnableJpaRepositories(basePackages = {"com.dnb.components.storage.repository"})
#Profile("inmemory")
public class InMemoryStandaloneStorageConfig extends BasicJpaStorageConfig {
....
(omitted for brevity)
UserResource.java:
#Component
#Path(UserResource.uri)
public class UserResource extends AbstractResource {
public final static String uri = BASE_URI + "/users";
#Override
public String getURI() {
return BASE_URI + uri;
}
#Autowired
private UserService userService;
...
It seems that the Spring Data JPA generated Repository class cannot be proxied either way without screwing up the auto-wiring.
Is there a fix for this? Is it even a good idea to annotate Repository methods with #Transactional? Should the annotation be at the service level only?

usually, we do not inject concrete classes but we inject interfaces.
this is my suggestion.
a. refactor UserService to UserServiceImpl class
b. create UserService interface
c. UserServiceImpl implements UserService
d. add "findAll" and "findOne" method declaration to UserService interface

Related

Can't inject repository in springboot

This is my repository:
#Repository
public interface GroupRepository extends JpaRepository<Group, Integer> {}
This is how I tried to use it in my service class:
#Service
public class GroupService {
private final GroupRepository groupRepository;
#Autowired
public GroupService(GroupRepository groupRepository) {
this.groupRepository = groupRepository;
}
Got this error :org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'groupController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'groupService' defined in file [/Users/nathanxuan/Files/Project/ratingApp/target/classes/com/xjy/service/GroupService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'groupRepository' defined in com.xjy.mapper.GroupRepository defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.xjy.pojo.Group
Does anyone know why this is happening? When I commented out the repository class everything works fine (I have another mapper class and that one also works).
-------edit-----------
This is the structure of my app:
I think the problem is with the model class Group, it needs the Entity annotation since you are using JPA. Try out this:
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Group {
....
}
Note: #Data #AllArgsConstructor #NoArgsConstructor comes from Lombok, so if you're not using it, just create regular Getter and Setter
Try removing #Repository from your repository. By extending from JpaRepository should be enough.
Unless you really need a setter injection defining your repository in the service like this should also be fine and more concise.
#Autowired
private GroupRepository groupRepository;

Spring Injecting implementation instead of interface

Here my class structure :
public interface CertificatService
{
}
The only one implementation
#Service
#Transactional
public class CertificatServiceImpl extends GestionCertificat implements CertificatService
{
}
And the injection :
#Service
#Transactional
public class ConnexionEbicsServiceImpl extends GestionConnexion implements ConnexionEbicsService
{
#Inject
private CertificatServiceImpl certificatService;
}
}
Injection the implementation causes injection failure :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'connexionEbicsServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tess2i.service.impl.CertificatServiceImpl com.tess2i.service.impl.ConnexionEbicsServiceImpl.certificatService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.tess2i.service.impl.CertificatServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#javax.inject.Inject()}
But if I inject the interface, it works :
#Service
#Transactional
public class ConnexionEbicsServiceImpl extends GestionConnexion implements ConnexionEbicsService
{
#Inject
private CertificatService certificatService;
}
}
But I need to inject the implementation so to benefit methods inherited from GestionCertificat
Can you help me to autowired the implementation. I understand that the real type is a proxy and not the implementation class CertificatServiceImpl as I would like. But what is the solution so ?
Thanks.
Perfect.
Just using proxy via CGLIB it is OK setting proxyTargetClass = true :
#EnableTransactionManagement(proxyTargetClass = true)
Thanks for the answer here : Spring - how to inject concrete interface implementation?

Cucumber Spring and class configuration

I'm struggling with Cucumber and Spring configuration.
I'm writing selenium framework using Page Object Pattern, with BrowserFactory.
When I use #ComponentScan, #Component and #Autowire annotations everything works fine, but when I want to create a bit more complicated bean with #Bean annotation (BrowserFactory which registers few browser drivers) in #Configuration class it does not work, during debug I'm getting nulls on every single variable I'm trying to Autowire.
I'm using Spring 4.2.4, all cucumber dependencies in version 1.2.4.
Config:
#Configuration
public class AppConfig {
#Bean
#Scope("cucumber-glue")
public BrowserFactory browserFactory() {
BrowserFactory browserFactory = new BrowserFactory();
browserFactory.registerBrowser(new ChromeBrowser());
browserFactory.registerBrowser(new FirefoxBrowser());
return browserFactory;
}
#Bean(name = "loginPage")
#Scope("cucumber-glue")
public LoginPage loginPage() throws Exception {
return new LoginPage();
}
#Bean(name = "login")
#Scope("cucumber-glue")
public Login login() {
return new Login();
}
}
POP:
public class LoginPage extends Page {
public LoginPage() throws Exception {
super();
}
...
}
Page:
public class Page {
#Autowired
private BrowserFactory browserFactory;
public Page() throws Exception{
...
}
}
Login:
public class Login {
#Autowired
private LoginPage loginPage;
public Login(){}
...
}
Steps:
#ContextConfiguration(classes = {AppConfig.class})
public class LoginSteps {
#Autowired
Login login;
public LoginSteps(){
}
#Given("^an? (admin|user) logs in$")
public void adminLogsIn(Login.User user) throws Exception {
World.currentScenario().write("Logging in as " + user + "\n");
login.as(user);
}
}
Error:
cucumber.runtime.CucumberException: Error creating bean with name 'LoginSteps': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: Login LoginSteps.login; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'login': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private LoginPage Login.loginPage; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginPage' defined in AppConfig: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [LoginPage]: Factory method 'loginPage' threw exception; nested exception is java.lang.NullPointerException
And now for the fun part...
BrowserFactory in World class is properly Autowired!!
World:
public class World {
#Autowired
private BrowserFactory browserFactory;
...
}
So I'll answer my own question:)
Issue was that I was calling BrowserFactory inside of Page constructor.
Looks like this bean was not yet created and was causing NPEs.
In order to fix that I:
Added #Lazy annotation to configuration (all elements that use this configuration, both defined in that class and those which will be found by Scan will be created as Lazy)
Moved call to Browser Factory to #PostConstruct method
Two more things to increase readability of Spring config:
Added #ComponentScan to configuration
Classes with no constructor parameters are annotated with #Component and #Scope("cucumber-glue") annotation so bean creation can be removed from AppConfig.class

#Override and #Transactional annotations

I use jpa, eclispelink and spring 3. I have UserDAO interface:
public interface UserDAO {
public void saveUser(User user);
}
and implementing class :
#Service
#Transactional
public class UserDAOImpl implements UserDAO{
#PersistenceContext
EntityManager em;
#Override
public void saveUser(User user) {
em.persist(user);
}
When I start app I have got error:
HTTP Status 500 - Servlet.init() for servlet appServlet threw exception<br>
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cartController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: foo.endpoints.UserEndpoint foo.controller.CartController.userEndpoint; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userEndpoint': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: foo.dao.UserDAOImpl foo.endpoints.UserEndpoint.userDAO; nested exception is java.lang.IllegalArgumentException: Can not set foo.dao.UserDAOImpl field foo.endpoints.UserEndpoint.userDAO to com.sun.proxy.$Proxy16
org.springframework.beans.factory.BeanCreationException: Could not autowire field: foo.endpoints.UserEndpoint foo.controller.CartController.userEndpoint; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userEndpoint': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: foo.dao.UserDAOImpl foo.endpoints.UserEndpoint.userDAO; nested exception is java.lang.IllegalArgumentException: Can not set foo.dao.UserDAOImpl field foo.endpoints.UserEndpoint.userDAO to com.sun.proxy.$Proxy16
but if I don't implement interface:
#Service
#Transactional
public class UserDAOImpl {
#PersistenceContext
EntityManager em;
public void saveUser(User user) {
em.persist(user);
}
everything work ok. I don't understand it. Maybe it is something with #Override method? Thanks
If you define an interface for your bean, then you must inject an instance of the interface, and not an instance of the concrete class:
#Autowired
private UserDAO userDAO;
and not
#Autowired
private UserDAOImpl userDAOImpl;
Because the actual bean instance is a JDK dynamic proxy which implements the interface and calls your implementation. It's not an instance of UserDAOImpl.

Scala with Spring: Constructor autowiring

I'm looking for "idiomatic" way to autowire Scala classes with Spring through constructor injection.
I've tried something like this:
#Component
class MyService #Autowired() ( val myDao: MyDao) extends Logging {
...
}
But I get an error:
Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [MyService]: No default constructor found; nested exception is java.lang.NoSuchMethodException: MyService.()
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:964) ~[spring-beans-3.0.7.RELEASE.jar:3.0.7.RELEASE]
I've added support for #Autowired on the constructor of a Scala object into the spring-scala project. This is only (at time of writing) in the nightly snapshot.
This allows you to do
#Component
#Autowired
class Service(dep : Dependency) { }
https://github.com/spring-projects/spring-scala
We use this style for a Spring MVC app:
#Component
class MyService extends Logging {
#Autowired
private val myDao: MyDao = null
}

Resources