Spring Boot JPA CrudRepository - spring

I'm working with Spring Boot + Spring Data JPA and facing this problem when trying to inject a class that extends CrudRepository:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'topicRepository': Could not resolve
matching constructor (hint: specify index/type/name arguments for
simple parameters to avoid type ambiguities)
Repository Class:
public interface TopicRepository extends CrudRepository<Topic, Integer> {}
Service Class:
#Service
public class TopicService {
#Autowired
private TopicRepository topicRepository;
}
Any suggestions?

I was having the same issue, and I fixed it by switching Spring Boot versions. Changing the Spring Data JPA versions did nothing (this is where I assumed the bug would be), so I think there is a bug in Spring Boot version 1.5.1. I switched back to version 1.4.3 and the error was gone. I didn't try subsequent/different versions, so you may just have to experiment with your dependencies and their versions.
For the record, you can have your service class annotated with #Repository, it shouldn't make any difference. I've been setting these apps up the same way using the service/dao pattern, and it has never been too picky with the annotations. Hopefully this may help others whose Spring Boot development flow suddenly throws an error!

Which versions of spring-data-commons and spring-data-jpa are you using. I just ran into this using spring-data-commons 1.13.x with spring-data-jpa 1.10.x. Upgrading spring-data-jpa to 1.11.x fixed the issue for me.

I too had the same issue after updating Spring Boot to 1.5.4.
I am also using spring-data-envers, which was at version 1.0.4. Upgrading to 1.4.1 solved the problem.
I hope it helps someone :)

Make sure:
1) TopicRepository is annotated with #Repository.
2) You have the scanning packages configured:
<jpa:repositories base-package="mypkg.repositories"></jpa:repositories>

Had the same issue on 1.5.2. Upgrading to 1.5.5 solved the problem.

You can use Applicationcontext to inject repository to this reference topicRepository..
You just declare applicationcontext in #rest controller class
Same like topicRepository by using annotation. Then you pass this to the service class which should take parms through constructor.
Ex-
public TopicService(Applicationcontext ctx) {this.topicRepository =context.getBean(TopicRepository.class);
}

Related

WebApplicationContext is always null in a spring boot test

My test class looks like this
#SpringBootTest(webEnvironment=WebEnvironment.MOCK)
public class sampleClassTest{
#Autowired
private WebApplicationContext wac;
}
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
In the setup method, wac is always null. From spring boot documentation, #SpringBootTest(webEnvironment=WebEnvironment.MOCK) always created a mock WebapplicaitonContext.
So I would expect it get autowired in the code above which doesn't happen.
Can someone tell me how to go about creating a webapplicationContext in this case so that it's not null like in my case ?
UPDATE
I am running spring boot tests invoking them from a class with springboot annotation.
Both test (springboottest) and calling class (springboot) application are in the same spring boot project under src/main/java.
I have nothing under src/main/test. I have done in this way because if classes from src/main/java want to call a test class then, it isn't really a test class.
Now, the problem is that I can't use runWith(SpringRunner.class) in springbootTest class. If I did that to get a mock webApplicationContext then, it gives me this error:
javax.management.InstanceAlreadyExistsException: org.springframework.boot:type=Admin,name=SpringApplication
I am not sure how to do about this.
To use #SpringBootTest you need to use Spring Framework's test runner. Annotate your test class with #RunWith(SpringRunner.class).
If someone is struggling with this issue in 2022 - please keep my defined precondions in mind. If you are using #SpringBootTest with defined port and constructor auto-wiring of the test class, the application context might be null.
It seems that the constructor dependency injection is eager and the cache aware context delegate of Spring is searching for a web application context which is no available yet. If you use field auto-wiring your test might run in a deterministic manner.
Whoever is facing this issue, make sure your spring boot starter parent version is compatible with spring cloud version in pom.xml
I was facing same issue, i resolved it by doing same.

Using the Grails Cache Plugin on Normal Spring Service Bean

i have some standard Spring #Service classes in a separate jar lib that use the standard #Cacheable Spring annotation, in a Spring boot project i declare the dependency, configure a CacheManager and just works!
i try to do the same in a Grails 3.1 project but with no luck!
i discover that https://github.com/grails-plugins/grails-cache require to use its 'proprietary' #Cacheable annotation:
http://grails-plugins.github.io/grails-cache/3.0.x/api/grails/plugin/cache/Cacheable.html
As workaround i FORKED some Service just to use the Grails #Cacheable and it's working but i'd like to have a single #Service that works under grails or not!
I have misconfigured something, it doesn't behave the same way, but i can't figure out what is it!
i'd like to share this jar lib between spring only & grails projects, but so far i can't make caching work, unless i forked the service calsses under
grails-app/services directory & used 'proprietary' #Cacheable annotation;
i try to remove the plugin and configure the bean and the cache in:
/GPsGrails3/grails-app/init/gpsgrails3/Application.groovy
with the org.springframework.context.annotation.Bean annotation:
#Primary
#Bean
public ConcurrentMapCacheManager concurrentMapCacheManager() {
return new ConcurrentMapCacheManager();
}
#Bean
public SignatureService signatureService() {
SignatureService _signatureService = new SignatureService();
return _signatureService;
}
i put signatureService under grails-app/services directory:
/GPsGrails3/grails-app/services/it/finmatica/ifw/impl/SignatureService.groovy
Maybe i have to configure my beans in:
/GPsGrails3/grails-app/conf/spring/resources.groovy ?
i have to use the version 4 of the plugin?
compile "org.grails.plugins:cache:4.+"
I am not sure what the question is but you don't have to use the Grails #Cacheable annotation. If you want to use the Spring one in a Grails app, you can, and it will behave in the same way that it would if you weren't using Grails. You don't even need the plugin in order to do that.

jpa 2.1 spring boot with web sphere 8.5.5.8(full version) jdk 7

i followed the approach suggested by jeff
https://gist.github.com/jeffsheets/aec3e94870ef903ce7efe33e00563d3c
I was able to overcome the jpa 2.1 java.lang.ClassCastException: com.ibm.websphere.persistence.PersistenceProviderImpl incompatible with javax.persistence.spi.PersistenceProvider.
But i get the following error A servlet named com.x...JerseyConfig can not be dynamically added because a servlet configuration with the same name already exists. i am using WebSphere 8.5.5.8 Full version with JDK 1.7 spring boot 1.4.0.M3.
In my JerseyConfig.java
#Component
#PropertySources(value = {
#PropertySource("classpath:application.properties"),
#PropertySource("classpath:ValidationMessages.properties")})
#DependsOn("hibernatePersistenceProviderResolver")
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("com.x.package");
}
}
Thanks for any hints or pointers.
I did the following to make it work (in addition to #DependsOn mentioned previously).
1) load local class loader first and parent last.
2) Add the JVM property at the WebSphere Appserver com.ibm.websphere.jaxrs.server.DisableIBMJAXRSEngine to true in order to use only the JAX RS shipped with the application. (which fixes the servlet name already exists).
3) After deploying successfully when i ran my REST endpoint i got the following error at run time.
UOWManager transaction processing failed; nested exception is com.ibm.wsspi.uow.UOWException: java.lang.VerifyError: com/ibm/websphere/uow/UOWSynchronizationRegistry.registerInterposedSynch ronizat ion(Ljavax/transaction/Synchronization)V
To fix this add spring.jta.enabled=false to use the WebShpere JTA. (Ideally prefer to override web sphere JTA and use spring JTA, need to figure out a way).

#Rollback(true) not working in spring boot 1.3.X

I have updated my pom from spring-boot-starter-parent 1.2.5.RELEASE to 1.3.2.RELEASE.
The problem is that everything stay the same but all the test #Rollback(true) not working at all after migration.
#Transactional
#Rollback(true)
#Test
public void testRollBack() {
dao.saveToDb();
throw new RunTimeException();
}
Configaturation:
#Bean
#Primary
public PlatformTransactionManager txManager() {
return new DataSourceTransactionManager(dataSource());
}
It works perfectly in the same configuration and code and the only change is spring boot version. I cannot see that Transaction is being created in logs as suppose too
Anyone has a clue? Maybe a way to debug and understand what is the problem?
Thanks
TransactionTestExecutionListener has changed quite a lot between Spring Framework 4.1 (used by Spring Boot 1.2) and Spring Framework 4.2 (used by Spring Boot 1.3). It sounds like there's been a change in behaviour which I suspect probably wasn't intentional.
To fix your problem without renaming one of your beans, you need to tell the test framework which transaction manager to use. The easiest way to do that is via the #Transactional annotation:
#Transactional("txManager")
#Rollback(true)
#Test
public void testRollBack() {
dao.saveToDb();
throw new RunTimeException();
}
I have put spring on debug..
There is a problem/bug in the test framework or i don't understand the use correctly.
I checked the code of spring and saw this:
bf.getBean(DEFAULT_TRANSACTION_MANAGER_NAME, PlatformTransactionManager.class);
This happens when we have several transaction manager, instead of getting the bean marked by #Primary annotation spring try to get transaction manager that called "transactionManager".
The solution is just mark the bean in that name.. Tried to open issue to spring-test project but don't know where.. If anyone knows how please advise.
Thanks
EDIT: So the solution is eiether what i have wrote above or just name them transaction(#Transactional("myManager")) and use it in the test method signature

#Qualifier and #Resource doesn't work when running test case under Spring test framework

I have a test case which has a dependency of 'ticketDao', like below:
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Qualifier;
public class LfnSaleCancellationIntegrationTest extends BaseIntegrationTest {
//#Resource(name = "baseTicketDao")
private BaseTicketDao ticketDao;
....
public void setTicketDao(#Qualifier("baseTicketDao") BaseTicketDao ticketDao) {
this.ticketDao = ticketDao;
}
}
and BaseIntegrationTest extends from spring test framework's AbstractJpaTests, Spring is v3.0.5
When run this test case, I got a similar exception:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [com.mpos.lottery.te.gamespec.sale.dao.BaseTicketDao]
is defined: expected single matching bean but found 2:
[baseTicketDao, extraballTicketDao]
My project has evolved a long time, in fact when I encountered this exception at the first time, #Qualifier solved it. Till today this project has changed much, but I really have no idea why #Qaulifier and #Resource don't work any more.
And if i remove the dependency of 'ticketDao', the test case will pass. I am wondering whether there are some change of spring configuration cause this exception? or ... i have googled much, but seem no other people ever faced such a problem, pls give your comments, thanks very much!
You are using AbstractJPATests which is part of old spring test framework and (indirect) subclass of AbstractDependencyInjectionSpringContextTests. By default the injection is not annotation based but it discovers setters and fields and attempts injection by type. It would be recommended to switch to newer annotation based tests, refer to spring documentation for details.
As a workaround try to change autowire mode. Call it in test constructor as this.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME), rename your field to baseTicketDao and remove setter.
I knew the reason. In my new project, there are a statement of context:component-scan in spring configuration file, which will register 4 BeanPostProcessors by default:
AutowiredAnnotationBeanPostProcessor(#Autowired)
RequiredAnnotationBeanPostProcessor(#Require)
CommonAnnotationBeanPostProcessor(JSR-250 annotations, #Resource, #PostConstruct etc, #WebServiceRef )
PersistenceAnnotationBeanPostProcessor(#PersistenceUnit and #PersistenceContext)
While in my old project, only the default BeanPostProcessor(internalAutoProxyCreator) has been registered. My understanding is AutowiredAnnotationBeanPostProcessor will always wire by type. Anyway if remove context:component-scan, my test case can pass now.
In fact i have migrate all my test cases to spring test context framework now, and context:component-scan must be stated, otherwise #Autowired, #Resource etc annotation will be ignored, and you will get a great many of NullPointerException of those automaticaly injected dependencies.
NOTE: <context:annotation-config/> will register those 4 BeanPostProcessors too.

Resources