What I understand so far is that when you use the #Transactional annotation any failure will cause the operation to rollback to its previous state.I have this method which adds Items to a quotation using spring PagingAndSortingRepository Interface.
#Override
public Quotation createNewQuotation(PurchaseRequest purchaseRequest, Supplier supplier) {
Quotation quotation = new Quotation();
Date now = new Date(Calendar.getInstance().getTimeInMillis());
quotation.setQuotationDate(now);
quotation.setPurchaseRequest(purchaseRequest);
quotation.setSupplier(supplier);
quotationRepository.save(quotation);
return quotation;
}
When I put a #Transactional annotation on the whole class and manually testing if the operation will rollback (by not selecting any supplier), other properties like quotationDate, PurchaseRequest is still stored in the database.
I get the feeling that I'm not using the #Transactional annotation. What might be the problem and what can I do to fix it?
Thanks for the replies.
I made this work by adding a #EnableTransactionManagement on my main class.
I solved the
The bean 'purchaseRequestServiceImpl' could not be injected as a
'com.eprocurement.service.PurchaseRequestServiceImpl' because it is a
JDK dynamic proxy that implements:
com.eprocurement.service.PurchaseRequestService Action: Consider
injecting the bean as one of its interfaces or forcing the use of
CGLib-based proxies by setting proxyTargetClass=true on #EnableAsync
and/or #EnableCaching.
by placing the #Transactional annotation on my service interfaces and #autowiring it instead of #autowiring my implementation classes.
Related
I know that there are questions similar to this one, but none of them have helped me. I'm following along this tutorial, and the part I can't wrap my mind around is:
#SpringBootApplication
public class Application {
private static final Logger log =
LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
#Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a couple of customers
...
// more lines, etc...
What I don't understand is where the repository passed into demo comes from. I know that the Autowired annotation can do something like that, but it isn't used at all here.
The more specific reason I ask is because I'm trying to adapt what they do here to an application I'm working on. I have a class, separate from all of the persistence/repository stuff, and I want to call repository methods like save and findAll. The issue is that the repository is an interface, so I can't instantiate an object of it to call the methods. So do I have to make a new class that implements the interface and create an object of that? Or is there an easier way using annotations?
When creating a #Bean, adding the repository in the parameters of the bean is enough to wire the repos in your bean. This works pretty much like adding #Autowired annotation inside a class that is annotated as #Component or something similar.
Spring works mostly with interface, since that is simplier to wire vs wiring concrete classes.
Can you try #Repository before the declaration of class? Worked for me in a Spring MVC structure.
#Repository
public class EntityDAOImpl implements EntityDAO{
...
}
The thing to wrap your head around is a Spring Boot application at startup time aims to resolve its dependancy tree. This means discovering and instantiating Beans that the application defines, and those are classes annotated with #Service, #Repository, etc.
This means the default constructor (or the one marked with #Autowire) of all beans is invoked, and after all beans have been constructed the application starts to run.
Where the #Bean annotation comes into play is if you have a bean which does not know the values of it's constructor parameters at compile time (e.g. if you want to wire in a "started at" timestamp): then you would define a class with an #Configuration annotation on it, and expose an #Bean method in it, which would return your bean and have parameters that are the beans dependencies. In it you would invoke the beans constructor and return the bean.
Now, if you want a certain method of some class to be invoked after the application is resolved, you can implement the CommandLineRunner interface, or you can annotate a method with #PostConstruct.
Some useful links / references:
https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
https://www.baeldung.com/spring-inject-prototype-bean-into-singleton
Running code after Spring Boot starts
Execute method on startup in Spring
So, I have an application running on WildFly10, which uses JSF, Spring (DI), JPA, Spring Data;
Right now we're trying to move it to CDI and remove Spring(DI). For now we'll keep Spring Data.
So, I set up CDI and made an EntityManager producer.
#Produces
#Dependent
#PersistenceContext
public EntityManager entityManager;
So, I'm able to inject repositories with CDI and all.
However on my original environment we had a custom repository factory,that was defined in my SpringConfiguration like this:
#EnableJpaRepositories(basePackages = {"com.foo.repository" }, repositoryFactoryBeanClass=CustomJpaRepositoryFactoryBean.class)
So, the question is, how can I define this repositoryFactoryBeanClass=CustomJpaRepositoryFactoryBean.class on a CDI environment?
The current implementation doesn't allow the configuration of the JpaRepositoryFactoryBean as one can see from the code where it gets instantiated.
So I guess you have the following options:
reimplement the instantiation process.
open a feature request.
do 2. and 1. in a reusable way and submit the result as a PR for the issue.
When trying to solve this problem I found that the custom impl was not being picked up. The solution suggested in this question helped me however: https://stackoverflow.com/a/38541669/188624
Basically is uses Java8 default interface method to provide the additional functionality. I had to use the "CDI.current().select" method to get hold of the entity manager though as property injection of course won't work.
I tested with Spring Data JPA 2.0.0
Spring appears fully capable of autowiring the correct type based on generic parameters without the need for #Qualifiers. However, as soon as I tack on a #Transactional annotation, it can no longer autowire based on generic parameters. Consider this example, invented only for purposes of illustrating the issue:
interface Product {}
interface Book extends Product {}
interface Toy extends Product {}
interface Store<P extends Product> {}
#Component
class BookStore implements Store<Book> {}
#Component
class ToyStore implements Store<Toy> {}
#Component
class BookDealer {
#Autowired
BookDealer(Store<Book> store) {
...
}
void inventoryBooks() {
... doesn't really matter what this does ...
}
}
Note that the above code wires up fine. The BookStore class is autowired into the BookDealer constructor without any issue. I can call inventoryBooks() and it works fine.
However, if I add a #Transactional annotation to a method upstream from the call to inventoryBooks(), e.g. on the client method that calls it, the BookDealer will no longer autowire, and I must resort to either injecting concrete types, or using a #Qualifier. The error is that there are two matching beans for the constructor argument of BookDealer, meaning both the BookStore and the ToyStore and Spring can't decide which one is needed. That tells me that Spring can no longer detect the generic types now that some upstream method has been proxied for the #Transactional. Something like that anyway...
I would like to stick to interfaces and not use #Qualifiers. Is there a way to do this with #Transactional, or is it a known limitation of generics and autowiring and things like #Transactional?
The Spring uses the JDK Proxy to generate the proxy used in AOP by default. The JDK proxy is based on the interface. So it maybe the problem, when you need to autowire the concrete class. So use the cglib instead(add the denpendency) and set the "" in the spring config file to "" and have a try. Hope it helps.
Using #Transaction annotation with #Autowired - Spring
In my test I manually instantiate a class that is being #Autowired in production. I hand inject it with #Autowired dependencies. On this class I call a method that is annotated with #Transactional and downstream uses a #PersistenceContext annotated EntitiyManager. The error I get is
No transaction aspect-managed TransactionStatus in scope
I would like to be able to programatically provide an EntityManager instance to be used by the context, but have no idea how to do this. Please advise. Also, please let me know if you need more background.
I am calling this #Transactional annotated method from my test from a Callable ran by an ExecutorService and therefore it has no access to ThreadLocal.
(Java 7 and Spring 4.1.1)
Assuming you are using #Transactional you may use #Transactional(value="myTransactionManager")
Also have you #Autowired the EntityManager in your class? Can you provide the class code?
Just get a working EM via #Autowired and set it where needed. Also check that your tests are marked as #Transactional.
I have a Spring AOP aspect used for logging, where a method can be included for logging by adding an annotation to it, like this:
#AspectLogging("do something")
public void doSomething() {
...
}
I've been using this on Spring beans and it's been working just fine. Now, I wanted to use it on a REST-service, but I ran into some problems. So, I have:
#Path("/path")
#Service
public class MyRestService {
#Inject
private Something something;
#GET
#AspectLogging("get some stuff")
public Response getSomeStuff() {
...
}
}
and this setup works just fine. The Rest-service that I'm trying to add the logging to now has an interface, and somehow that messes stuff up. As soon as I add the #AspectLogging annotation to one of the methods, no dependencies are injected in the bean, and also, the aspect is newer called!
I've tried adding an interface to the REST-service that works, and it gets the same error.
How can having an interface lead to this type of problems? The aspect-logger works on classes with interfaces elsewhere, seems it's only a problem when it's a REST-service..
Ref the below Spring documentation (para 2) -
To enable AspectJ annotation support in the Spring IoC container, you
only have to define an empty XML element aop:aspectj-autoproxy in your
bean configuration file. Then, Spring will automatically create
proxies for any of your beans that are matched by your AspectJ
aspects.
For cases in which interfaces are not available or not used in an
application’s design, it’s possible to create proxies by relying on
CGLIB. To enable CGLIB, you need to set the attribute
proxy-targetclass= true in aop:aspectj-autoproxy.
In case your class implements an interface, a JDK dynamic proxy will be used. However if your class does not implement any interfaces then a CGLIB proxy will be created. You can achieve this #EnableAspectJAutoProxy. Here is the sample
#Configuration
#EnableAspectJAutoProxy
public class AppConfig {
#Bean
public LoggingAspect logingAspect(){
return new LoggingAspect();
}
}
#Component
#Aspect
public class LoggingAspect {
...
...
}
In my opinion what you are actually trying to do is to add spring annotations to a class maintained by jersey. In the result you are receiving a proxy of proxy of proxy of somethng. I do not think so this is a good idea and this will work without any problems. I had a similar issue when I tried to implement bean based validation. For some reasons when there were #PahtParam and #Valid annotations in the same place validation annotations were not visible. My advice is to move your logging to a #Service layer instead of #Controller.