How to avoid the serialization exception (NotSerializableException) with Spring Data - spring

I have a problem with Spring Data, I receive some exception of NotSerializableException type.
Below an example to explain how I have this problem :
#Component
#Scope("session")
public class Bean implements Serializable {
#Autowired
private FooRepository repository;
}
public interface FooRepository extends JpaRepository<Foo, Long>
After I look into in the code, I have seen that the interface org.springframework.data.repository.Reposotiry is not serializable.
And the last version of Spring Data hasn't changed.
I could override the serilization but I don't know if it's the best solution.
Could you tell me if you have found an other solution for this problem or workaroud.
Thank in advance.

You will "get the exception" when an instance must implement Serializable. The exception is thrown by either the serialization run-time or by the instance of the class.
I think the simplest fix is to make FooRepository "serializable", but eventually you cannot since it's a third-party library. So, in your case you must "mark" it as transient; once you do that it will be ignored by the serializable run-time.
#Component
#Scope("session")
public class Bean implements Serializable {
#Autowired
private transient FooRepository repository;
}
NOTE: That's in theory, I've never done that with an injected bean, but the result should be the same. Anyway, that applies to your issue, maybe not to your specific solution.

Related

Spring Boot detects 2 identical repository beans

I am using Spring Boot with Spring Data JPA, there is only one #SpringBootApplication. And I have also a repository classes, for example:
package com.so;
public interface SORepository {
//methods
}
And impl
#Repository("qualifier")
#Transactional(readOnly = true)
public class SORepositoryImpl implements SORepository {
//methods
}
The proplem is, when I start the application, I get following error:
Parameter 0 of constructor in com.so.SomeComponent required a single bean, but 2 were found:
- qualifier: defined in file [path\to\SORepositoryImpl.class]
- soRepositoryImpl: defined in file [path\to\SORepositoryImpl.class]
So, as you see, somehow 2 beans of one repository class are created. How can I fix this?
You can use Spring Data JPA methods having created Proxy element and than inject it into public class SORepositoryImpl:
public interface Proxy() extends JpaRepository<Element, Long>{
Element saveElement (Element element); //ore other methods if you want}
And than:
#Repository
#Transactional(readOnly = true)
public class SORepositoryImpl implements SORepository {
#Autowired
private Proxy proxy;
//end realisation of methods from interface SORepository
}
Try taking the #Repository annotation off the SORepositoryImpl class
e.g.
#Transactional(readOnly = true)
public class SORepositoryImpl implements SORepository {
//methods
}
The error message is implying you have two beans, one named "qualifier" and one named "soRepositoryImpl", which is probably in a Config class.
I guess you should share your SomeComponent class supposing you have no extra configuration class/xml. My take is that you are injecting as 'soRepositoryImpl' there where you have defined as 'qualifier'. Having two options them. I would say to just remove the annotation parameter 'qualifier' and it should work.
Moreover, unless you want do specify an custom DAO implementation you can avoid #Repository at all (That's an annotation you use to make it injectable for your services). You can just create an interface extending Spring interface and define methods for queries.
For example:
public interface PersonRepository extends Repository<User, Long> {
List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
Then you can just inject it in your services/controller directly.
private final PersonRepository personRepository;
public PersonController(final PersonRepository personRepository) {
this.personRepository = personRepository;
}
check samples:
https://spring.io/guides/gs/accessing-data-jpa/
http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html
OK, I've found the issue.
I just couldn't understand, how Spring creates the second bean (soRepositoryImpl), because I've never told it, neither explicitly nor in config classes. But I figured out that the second bean us created during the instantiation of my another SORepository (which is in the different package com.another and which extends JpaRepository).
So, when Spring tries to resolve all dependencies of com.another.SORepository it somehow finds my com.so.SORepositoryImpl (which has nothing familiar with com.another.SORepository - not extending\implementing, not jpa stuff, only similar names!).
Well it seems like a Spring bug to me, because it doesn't check the real inheritance of dependent classes of repositories, only name + Impl (even in different package) suits for him.
The only thing that I should do is to rename `com.so.SORepositoryImpl and that it, no 2 beans anymore.
Thanks everyone for answers!

Error in Auto wiring component

I am getting a weird issue while using #Autowired annotation
I am injecting one spring component into another spring component like below
import com.myutil.GenericUtils;
#Component
public class MyDomainImpl implements MyDomain {
#Autowired
private GenericUtils genericUtils;
}
and this works fine
When I try to inject the same component a different component ( which is implementing a generic interface ) , it throws the below error.
java.lang.IllegalArgumentException: The argument does not represent an annotation type: Autowired
This is the code which throws the error
import com.myutil.GenericUtils;
#Component
public class MyMapper implements GenericMapper<Mycomponent,MycomponentSO>{
#Autowired
private GenericUtils genericUtils;
}
I am seeing this error first time using Spring FW.
I tried to find out the root cause , but no luck.
If I remove the autowiring , the compilation error does not occur
In case if anybody has faced this error, please advise the solution
Thanks
Lives
I think the problem in auto-wiring MyMapper not auto-wiring GenericUtils, if you are auto-wiring it using interface GenericMapper try to change it to MyMapper as:
#Autowired
private GenericMapper myMapper ;
to
#Autowired
private MyMapper myMapper ;
if it is working so mostly you have a proxy wrapping your bean.
Update:
after re review the error again I found it is most probably coming from java it self, specially from RoundEnvironment it have getElementsAnnotatedWith and this method is throw exception as
IllegalArgumentException - if the argument does not represent an
annotation type
which is your case which is meaning that it is not considering Autowired as annotation type so please check if you have any other class with name Autowired may it is imported wrongly, or you have some missing jars in your build.

Trying to generate error about Spring's #Autowired field injection for JUnit

I am working with Spring 4.0.7, and with JUnit about testing of course.
About DI Spring offers #Autowired to be used in three locations
constructor
setter
field
I always work through the two first, why never the third option?
Because I remember have read long time ago about field injection should not be used, because it has a negative consequence about Testing. It does JUnit fails.
Note: Only for Testing is the problem. To runtime or production all goes well
Objective: For demonstration/academic purposes I want generate this problem.
I have the following:
Repository
public interface PersonRepository extends JpaRepository<Person, String>{
}
A Service
#Service
#Transactional
#Profile("failure")
public class PersonFailTestServiceImpl implements PersonService {
private static final Logger logger = ...
#Autowired
private PersonRepository personRepository;
Other Service (calling or using the service shown above)
#Service
#Transactional
#Profile("failure")
public class PersonFailTestProcessImpl implements PersonProcess {
private static final Logger logger = ...
#Autowired
private PersonService personService;
How you can see the two services are based on Field Injection.
Now the testing:
How the beans are loaded
#Configuration
#ComponentScan( basePackages={"com.manuel.jordan.server.infrastructure"},
basePackageClasses={PersonProcess.class,PersonRepository.class, PersonService.class})
public class CentralConfigurationEntryPoint {
}
#ContextConfiguration(classes=CentralConfigurationEntryPoint.class)
public class CentralTestConfigurationEntryPoint {
}
Now the two testing classes
#Transactional
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles({"development","failure"})
public class PersonServiceImplDevelopmentFailureTest extends CentralTestConfigurationEntryPoint {
#Autowired
private PersonService personService;
#Test
public void savePerson01(){
Person person01 = PersonFactory.createPerson01();
personService.save(person01);
personService.printPerson(personService.findOne("1"));
}
#Transactional
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles({"development","failure"})
public class PersonProcessImplDevelopmentFailureTest extends CentralTestConfigurationEntryPoint{
#Autowired
private PersonProcess personProcess;
Well all the testing methods pass, all green. I don't know if I am missing something or through Spring 4 the problem has been fixed
If this was your premise or problem
Because I remember have read long time ago about field injection
should not be used, because it has a negative consequence about
Testing. It does JUnit fails.
then you thought wrong. There is nothing inherently wrong with using field injection, definitely nothing that would cause JUnit tests to fail in and of itself. If a bean exists, Spring will be able to inject it whether it's in a constructor, a setter method, or a field.
Since you've activated your failure profile, your PersonFailTestServiceImpl bean will be found.
I think I can help. The example code you've posted here is a good example of a system / integration test, not a UNIT test.
If you were UNIT testing PersonFailTestProcessImpl, you would have to set the personRepository dependency yourself through code. But it is private, so how do you do this? You cannot use a constructor or setter since none is provided. This is what is meant by 'hard to unit test'.
Java 5+ provides a way to set private variables like this via reflection (the so-called privileged accessor). Basically, you obtain the class, get the declared field, call its setAccessible method, then you can set its value directly. There are libraries that will do these steps for you, but the point is that this is a pain compared to X.setSomething();
So there is nothing that 'makes jUnit fails' by using #Autowired on a private field. But building an object model without constructors or setters for establishing dependencies is unnecessarily constraining.

Where should #Service annotation be kept? Interface or Implementation?

I'm developing an application using Spring. I need to use the #Service annotation. I have ServiceI and ServiceImpl such that ServiceImpl implements ServiceI. I'm confused here as to where should I keep the #Service annotation.
Should I annotate the interface or the implementation with #Service? What are the differences between these two approaches?
I never put #Component (or #Service, ...) at an interface, because this make the interface useless. Let me explain why.
claim 1: If you have an interface then you want to use that interface for the injection point type.
claim 2: The purpose of an interface is that it define a contract that can been implemented by several implementations. On the other side you have your injection point (#Autowired). Having just one interface and only one class that implement it, is (IMHO) useless, and violates YAGNI.
fact: When you put:
#Component (or #Service, ...) at an interface,
have multiple classes that implements it,
at least two classes become Spring Beans, and
have an injection point that use the interface for type based injection,
then you will get and NoUniqueBeanDefinitionException
(or you have a very special configurations setup, with Environment, Profiles or Qualifiers ...)
Conclusion: If you use #Component (or #Service, ...) at an interface then you must violate at least one of the two clains. Therefore I think it is not useful (except some rare scenarios) to put #Component at interface level.
Spring-Data-JPA Repository interfaces are something complete different
Basically annotations like #Service, #Repository, #Component, etc. they all serve the same purpose:
auto-detection when using annotation-based configuration and classpath
scanning.
From my experience I am always using #Service annotation on the interfaces or abstract classes and annotations like #Component and #Repository for their implementation. #Component annotation I am using on those classes which serves basic purposes, simple Spring beans, nothing more. #Repository annotation I am using in the DAO layer, for e.g. if I have to communicate to the database, have some transactions, etc.
So I would suggest to annotate your interface with the #Service and other layers depending on the functionality.
I used #Component, #Service, #Controller and #Repository annotations only on the implementation classes and not on the interface. But #Autowired annotation with Interfaces still worked for me. If there's only one implementation of your interface Spring component scan automatically finds it with just #Autowired annotation. In case you have multiple implementations, you will need to use the #Qualifier annotation along with #Autowired to inject the correct implementation at the injection point.
1. #Service on Interfaces
#Service
public interface AuthenticationService {
boolean authenticate(String username, String password);
}
Normally, that's fine, but there's a drawback. By putting Spring's #Service on interfaces, we create an extra dependency and couple our interfaces with an outside library.
Next, to test the autodetection of our new service beans, let's create an implementation of our AuthenticationService:
public class InMemoryAuthenticationService implements AuthenticationService {
#Override
public boolean authenticate(String username, String password) {
//...
}
}
We should pay attention that our new implementation, InMemoryAuthenticationService, doesn't have the #Service annotation on it. We left #Service only on the interface, AuthenticationService.
So, let's run our Spring context with the help of a basic Spring Boot setup:
#SpringBootApplication
public class AuthApplication {
#Autowired
private AuthenticationService authService;
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
When we run our app, we may get the infamous NoSuchBeanDefinitionException, and the Spring context fails to start.
Therefore, placing #Service on interfaces isn't enough for the auto-detection of Spring components.
2. #Service on Abstract Classes
Using the #Service annotation on abstract classes isn't common.
We'll start by defining an abstract class from scratch and putting the #Service annotation on it:
#Service
public abstract class AbstractAuthenticationService {
public boolean authenticate(String username, String password) {
return false;
}
}
Next, we extend AbstractAuthenticationService to create a concrete implementation without annotating it:
public class LdapAuthenticationService extends AbstractAuthenticationService {
#Override
public boolean authenticate(String username, String password) {
//...
}
}
Accordingly, we also update our AuthApplication, to inject the new service class:
#SpringBootApplication
public class AuthApplication {
#Autowired
private AbstractAuthenticationService authService;
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
After we run our AuthApplication, the Spring context doesn't start. It ends up with the same NoSuchBeanDefinitionException exception again.
So, using #Service annotation on abstract classes doesn't have any effect in Spring.
3. #Service on Concrete Classes
Contrary to what we've seen above, it's quite a common practice to annotate the implementation classes instead of abstract classes or interfaces.
In this way, our goal is mostly to tell Spring this class is going to be a #Component and mark it with a special stereotype, which is #Service in our case.
Therefore, Spring will autodetect those classes from the classpath and automatically define them as managed beans.
So, let's put #Service on our concrete service classes this time around. We'll have one class that implements our interface and a second that extends the abstract class that we defined previously:
#Service
public class InMemoryAuthenticationService implements AuthenticationService {
#Override
public boolean authenticate(String username, String password) {
//...
}
}
#Service
public class LdapAuthenticationService extends AbstractAuthenticationService {
#Override
public boolean authenticate(String username, String password) {
//...
}
}
We should take notice here that our AbstractAuthenticationService doesn't implement the AuthenticationService here. Hence, we can test them independently.
Finally, we add both of our service classes into the AuthApplication and give it a try:
#SpringBootApplication
public class AuthApplication {
#Autowired
private AuthenticationService inMemoryAuthService;
#Autowired
private AbstractAuthenticationService ldapAuthService;
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
Our final test gives us a successful result, and the Spring context boots up with no exceptions. Both of the services are automatically registered as beans.
You might have a look at this page for the other explanations.
Pros of putting annotation on #Service is that it gives a hint that it is a service. I don't know if any implementing class will by default inherit this annoation.
Con side is that you are coupling your interface with a specific framework i.e. Spring, by using spring specific annotation.
As interfaces are supposed to be decoupled from implementation, I would not suggest using any framework specific Annotations or object part of your interface.
I would put #Service on your class but put the name of the interface as a parameter to the annotation e.g.
interface ServiceOne {}
#Service("ServiceOne")
class ServiceOneImpl implements ServiceOne{}
By doing that you get all the benefits and can still inject the interface but get the class
#Autowired
private ServiceOne serviceOne;
So your interface is not tied to spring framework and you can change the class at any time and not have to update all your injection points.
So if I wanted to change the implementation class I could just annotate the new class and remove from the first but that's all that is required to be changed. If you inject the class you could have a lot of work when ever you want to change the impl class.
One benefit of spring is to easily switch Service (or other) implementation.
For this, you need to annotate on the interface and declare variable like this :
#Autowired
private MyInterface myVariable;
and not :
#Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;
Like the first case, you can activate which implementation to inject from the moment it is unique (only one class implements the interface).
In the second case, you need to refactor all your code (the new class implementation has another name).
As a consequence, the annotation needs to be on the interface as much as possible. Furthermore, JDK proxies are well suited for this : they are created and instantiated at application startup because runtime type is known by advance, contrary to CGlib proxies.
interface MyService {}
#Service
class MyServiceImpl implements MyService{}
#Autowired
private MyService myService;
My testing result on spring-boot 2.7.4 is:
Adding #Service ONLY to interface doesn't create spring bean named MyService. It will error on Autowired.
#Service will need to be added to implementation class to create bean com.*.service.impl.MyServiceImpl $$EnhancerBySpringCGLIB$$9140ae19 Spring will wire it to private MyService myService;
There are 5 annotations which could be used for making spring beans. List in below of answers.
Do you really need an interface? If you are going to have one implementation for each service interface, just avoid it, use only class. Of course, if you don't have RMI or when interface proxy is required.
#Repository - use for injecting your dao layer classes.
#Service - use for injecting your service layer classes. In service layer also you might need to use #Transactional annotation for db transaction management.
#Controller - use for your frontend layer controllers, such as JSF managed beans injecting as spring beans.
#RestController - use for spring rest controllers, this would help you to avoid every time to put #ResponseBody and #RequestBody annotations in your rest methods.
#Component - use it in any other case when you need to Inject spring bean which is not controller, service, or dao class
To put it simply:
#Service is a Stereotype annotation for the service layer.
#Repos­itory is a Stereotype annotation for the persis­tence layer.
#Component is a generic stereotype annotation used to tell Spring to create an instance of the object in the Appl­ication Context. It's possible to
define any name for the instance, the default is the class name as camel case.

Spring MVC + Hibernate DAOs : unable to wire beans

I'm currently working on a Spring MVC project in which I integrated Hibernate. The pure Spring MVC part (DispatcherServlet + request mapping) works fine. Now, the problem I have to cope with is quite strange : I've read "Java Persistence with Hibernate" and I am trying to design my persistence layer in a similar way than explained in the book. That is, I've designed it in two parallel hierarchies : one for implementation classes and a second for the interfaces.
So, I have an abstract class named GenericDaoImpl, that implements the GenericDao interface. Then I have a concrete class named AdvertisementDaoImpl, that extends GenericDaoImpl and that implements the AdvertisementDao interface (which extends GenericDao).
Then, in a service bean (class marked with #Service), I'll have my dao class autowired.
Here's my problem :
autowiring a DAO class that implements an interface but does not extends my abstract GenericDaoImpl class : OK
autowiring my AdvertisementDaoImpl that implements the AdvertisementDao interface and extends my abstract GenericDaoImpl class : leads to bean initialization exception.
The abstract class I have at the top of my DAO hierarchy handles all the boilerplate code for common CRUD methods. So, I definitely want to keep it.
Does anyone have an explanation about that?
Here's an excerpt of code :
public abstract class GenericDaoImpl <T, ID extends Serializable> implements BeanPostProcessor, GenericDao<T, ID>{
#Autowired(required=true)
private SessionFactory sessionFactory;
private Session currentSession;
private Class<T> persistentClass;
...
}
#Repository
public class AdvertisementDaoImpl extends GenericDaoImpl<Advertisement, Long> implements AdvertisementDao {
...
public List<Advertisement> listAdvertisementByType(AdvertisementType advertisementType, Class<? extends Good> type) {
return null;
}
}
#Service
public class AdvertisementServiceImpl implements AdvertisementService{
#Autowired(required=false)
private AdvertisementDao advertisementDao;
public List<Advertisement> listAllAdvertisements() {
return null;
}
}
Here's the most relevant part of the stacktrace (at least, I guess it is):
nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: be.glimmo.service.AdvertisementService
be.glimmo.controller.HomeController.advertisementService; nested
exception is java.lang.IllegalArgumentException: Can not set
be.glimmo.service.AdvertisementService field
be.glimmo.controller.HomeController.advertisementService to
be.glimmo.dao.AdvertisementDaoImpl
And here's my Spring configuration (link to pastebin.com) :
I believe you should use proxy-target-class in your transaction management configuration:
<tx:annotation-driven transaction-manager="transactionManagerForHibernate"
proxy-target-class="true" />
The symptoms of the problem you describe match the ones mentioned in Spring Transaction Management (look for Table 10.2) and AOP proxying with Spring:
If the target object to be proxied implements at least one interface
then a JDK dynamic proxy will be used. All of the interfaces
implemented by the target type will be proxied. If the target object
does not implement any interfaces then a CGLIB proxy will be created.
So, when CGLIB is not there by default, you have all the methods coming from implemented interfaces but you will miss proxying of the methods that come from super classes in the hierarchy and that's why you get an exception on this.
After a few more tests, it turns out that the problem was caused by my abstract GenericDaoImpl class implementing BeanPostProcessor interface : for some reason, the methods from this interface were executed not only at this bean instantiation but at every bean intantiation.
Given that, within my BeanPostProcessor hook methods, I was retrieving generics parameterized types, when these methods were executed against classes that are not in my DAO hierarchy, they would end up yielding runtime Exceptions (more specifically, ClassCastException).
So, to solve this issue, I had my GenericDaoImpl class not implement BeanPostProcessor interface anymore and I moved the body of the hook method in the empty contructor.

Resources