I'm getting the following exception when I run the app
Could someone advise what might be the issues?
Exception in thread "task-2" java.lang.IllegalStateException: EntityManagerFactory is closed
at org.hibernate.internal.SessionFactoryImpl.validateNotClosed(SessionFactoryImpl.java:509)
at org.hibernate.internal.SessionFactoryImpl.getProperties(SessionFactoryImpl.java:503)
at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.findDataSource(DataSourceInitializedPublisher.java:105)
at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.publishEventIfRequired(DataSourceInitializedPublisher.java:97)
at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.access$100(DataSourceInitializedPublisher.java:50)
at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher$DataSourceSchemaCreatedPublisher.lambda$postProcessEntityManagerFactory$0(DataSourceInitializedPublisher.java:200)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in ru.javamentor.ecommerce.service.impl.ReadWriteServiceImpl required a single bean, but 4 were found:
- productCategoryDaoImpl: defined in file [D:\Project\ecommerce\target\classes\ru\javamentor\ecommerce\dao\impl\ProductCategoryDaoImpl.class]
- productDaoImpl: defined in file [D:\Project\ecommerce\target\classes\ru\javamentor\ecommerce\dao\impl\ProductDaoImpl.class]
- roleDaoImpl: defined in file [D:\Project\ecommerce\target\classes\ru\javamentor\ecommerce\dao\impl\RoleDaoImpl.class]
- userDaoImpl: defined in file [D:\Project\ecommerce\target\classes\ru\javamentor\ecommerce\dao\impl\UserDaoImpl.class]
ReadWriteServiceImpl class:
#Service
public class ReadWriteServiceImpl<T, PK> implements ReadWriteService<T, PK> {
private final ReadWriteDao<T, PK> readWriteDao;
#Autowired
public ReadWriteServiceImpl(ReadWriteDao<T, PK> readWriteDao) {
this.readWriteDao = readWriteDao;
}
#Override
#Transactional
public void persist(T t) {
readWriteDao.persist(t);
}
#Override
#Transactional
public void update(T t) {
readWriteDao.update(t);
}
#Override
#Transactional
public void delete(T t) {
readWriteDao.delete(t);
}
#Override
public boolean existsById(PK id) {
return readWriteDao.existsById(id);
}
#Override
public T getByKey(PK id) {
return readWriteDao.getByKey(id);
}
#Override
public List<T> getAll() {
return readWriteDao.getAll();
}
}
In this case the reason for exception is clear:
There are 4 candidates for injection to ReadWriteServiceImpl and spring doesn't know which of the beans to inject:
public ReadWriteServiceImpl(ReadWriteDao<T, PK> readWriteDao) {
this.readWriteDao = readWriteDao;
}
There are 4 candidates - implementations of ReadWriteDao and spring lists them all in the exception...
There are three ways you can go with in this case:
Use Concrete type (or create an interface for that concrete implementation and inject by that interface so that spring won't be confused)
Use #Qualifier annotation as a hint to spring framework what to inject
Use #Primary annotation if you think that one repository should be used "by default" to resolve confusions like this.
It showed me the error because I was writing wrong on the path
#GetMapping(myEndpoint+ "/${id}")
I should have written:
#GetMapping(myEndpoint+ "/{id}")
Related
I have a Spring Boot + Apache Camel project that works brilliantly. I just added a new bean though where I wanted to have its implementation be profile-specific. I created Spring tests to verify it, and it works as expected, but when I run the server I get the following stack trace:
Caused by: org.apache.camel.NoSuchBeanException: No bean could be found in the registry for: MyFancyBean
at org.apache.camel.component.bean.RegistryBean.getBean(RegistryBean.java:94)
at org.apache.camel.model.language.MethodCallExpression.createExpression(MethodCallExpression.java:196)
at org.apache.camel.model.language.MethodCallExpression.createPredicate(MethodCallExpression.java:210)
at org.apache.camel.model.language.ExpressionDefinition.createPredicate(ExpressionDefinition.java:148)
at org.apache.camel.model.ValidateDefinition.createProcessor(ValidateDefinition.java:63)
at org.apache.camel.model.ValidateDefinition.createProcessor(ValidateDefinition.java:35)
at org.apache.camel.model.ProcessorDefinition.makeProcessorImpl(ProcessorDefinition.java:545)
at org.apache.camel.model.ProcessorDefinition.makeProcessor(ProcessorDefinition.java:506)
at org.apache.camel.model.ProcessorDefinition.addRoutes(ProcessorDefinition.java:222)
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:1068)
I have an interface and two implementations:
public interface MyFancyBean { ... }
public class FooFancyBean implements MyFancyBean { ... }
public class NonFooFancyBean implements MyFancyBean { ... }
Depending on profile, the correct bean is read instantiated:
#Configuration
public class AppConfig {
#Bean
#Profile("foo")
MyFancyBean fooBean() {
return new FooFancyBean();
}
#Bean
#Profile("!foo")
MyFancyBean nonFooBean() {
return new NonFooFancyBean();
}
}
I've verified this works a couple of ways. First, a couple tests:
#ActiveProfiles("anything-but-foo")
#RunWith(SpringJUnit4ClassRunner.class)
#ComponentScan(basePackages = {"com.example", "com.jtv.spring.boot"})
#EnableAutoConfiguration
#Component
public class NonFooBean_SpringTest {
#Autowired
private MyFancyBean bean;
#Test
// ... here "bean" is instantiated as "NonFooFancyBean"
So the test works.
Further, when I start my app, depending on profile the correct bean in my #Configuration class above is called.
But Camel is still angry and says "NoSuchBeanException" on startup.
FWIW, here's how I'm referencing the bean:
#Component
public class MyCamelRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
// [...]
from("direct:processStuff").
validate().method("MyFancyBean").
process("MyProcessor");
}
}
How do I get Camel to honor this config?
Whoooo... Y'all get to be my rubber duck today. I just autowired it. (This doesn't work for my processor, which is why it didn't occur to me initially.)
#Component
public class MyCamelRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
// [...]
#Autowired MyFancyBean myFancyBean;
from("direct:processStuff").
validate().method(myFancyBean).
process("MyProcessor");
}
}
I'm using Spring 4.3.8.RELEASE with Hibernate 5.1.5.Final. I want to have a method executed after another another transaction completes. That transaction is defined below
#Service("organizationService")
#Transactional
public class OrganizationServiceImpl implements OrganizationService, ApplicationEventPublisherAware
{
private ApplicationEventPublisher publisher;
#Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher)
{
this.publisher = publisher;
}
#Override
public void save(Organization organization)
{
...
// sync data with ThirdParty but only if something has definitelychanged on the SB
// side, in which case we want to send ThirdParty an update.
if (!hasSameAttributes)
{
publisher.publishEvent(new ThirdPartyOrganizationEvent(organization.getId()));
} // if
} // save
So here is the method that I want executed after the above transaction completes ...
#Service
public class ThirdPartyAPIServiceImpl implements ThirdPartyAPIService
{
#Override
#TransactionalEventListener
public boolean updateOrg(final ThirdPartyOrganizationEvent thirdPartyOrgEvent)
{
...
}
But when I load my application context I get this error
Caused by: java.lang.IllegalStateException: No TransactionalEventListener annotation found on method: public abstract boolean org.mainco.subco.myproject.service.ThirdPartyAPIService.updateOrg(org.mainco.subco.myproject.domain.ThirdPartyOrganizationEvent)
at org.springframework.transaction.event.ApplicationListenerMethodTransactionalAdapter.<init>(ApplicationListenerMethodTransactionalAdapter.java:55)
at org.springframework.transaction.event.TransactionalEventListenerFactory.createApplicationListener(TransactionalEventListenerFactory.java:55)
at org.springframework.context.event.EventListenerMethodProcessor.processBean(EventListenerMethodProcessor.java:159)
at org.springframework.context.event.EventListenerMethodProcessor.afterSingletonsInstantiated(EventListenerMethodProcessor.java:104)
... 34 more
Wbat do I need to do to get this configured properly?
Defining #TransactionalEventListener on interface method rather then on method implementing interface worked for me.
I have a Resource which injects the following class
#Component
public class CustomDozerBeanMapper implements Mapper {
private final DozerBeanMapper beanMapper;
public CustomDozerBeanMapper() {
this.beanMapper = new DozerBeanMapper();
BeanMappingBuilder builder = new BeanMappingBuilder() {
protected void configure() {
//some mapping stuff
}
};
beanMapper.addMapping(builder);
}
#Override
public <T> T map(Object o, Class<T> aClass) throws MappingException {
return beanMapper.map(o, aClass);
}
#Override
public void map(Object o, Object o1) throws MappingException {
beanMapper.map(o, o1);
}
#Override
public <T> T map(Object o, Class<T> aClass, String s) throws MappingException {
return beanMapper.map(o, aClass, s);
}
#Override
public void map(Object o, Object o1, String s) throws MappingException {
beanMapper.map(o, o1, s);
}
}
In my applicationContext.xml I have declared
<context:annotation-config/>
<context:component-scan base-package="foo.bar"/>
<bean id="customDozerMapper" class="foo.bar.CustomDozerBeanMapper" />
Then in our resource I inject it
class SomeResource {
#Inject CustomDozerMapper customDozerMapper;
//We have loads of other Injects which work just fine, only this class has problems
}
Caused by: A MultiException has 1 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=CustomDozerBeanMapper,parent=SomeResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,1098507248)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:75)
at org.jvnet.hk2.internal.Utilities.justInject(Utilities.java:947)
at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:975)
at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:965)
at org.glassfish.jersey.server.spring.SpringComponentProvider$SpringManagedBeanFactory.provide(SpringComponentProvider.java:191)
at org.jvnet.hk2.internal.FactoryCreator.create(FactoryCreator.java:153)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at org.jvnet.hk2.internal.PerLookupContext.findOrCreate(PerLookupContext.java:70)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2072)
at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:761)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:700)
at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:172)
at org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:284)
at org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:74)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:109)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
Now if I change and use #Autowired, it works fine
We are using Spring for dependency management, but for some reason h2k is being used, and I get the following exception
Can anyone please explain what the problem might be?
Why does it work with #Autowired and not #Inject
Why is h2k being used, and not Spring?
Probably, the problem may be because of 2 bean declarations (one in the XML configuration and the another one with #Component) and a DI container couldn't able to pick up one of them.
All solutions that are available here:
removing one of the bean definitions (I'd prefer the XML one)
specifying a bean by the #Qualifier or #Named annotation
The problem might also be due to the bean name in config file customDozerMapper and actual injection customerDozerMapper are not matching. If #inject does not find matching bean, it throws an exception. However, there is provision for #autowired wherein you can set attribute required=false and it injects null if it does not find matching bean.
Note: Configuration in config xml overrides the annotation
configuration.
Is it possible to access beans defined outside of the step scope? For example, if I define a strategy "strategyA" and pass it in the job parameters I would like the #Value to resolve to the strategyA bean. Is this possible? I am currently working round the problem by getting the bean manually from the applicationContext.
#Bean
#StepScope
public Tasklet myTasklet(
#Value("#{jobParameters['strategy']}") MyCustomClass myCustomStrategy)
MyTasklet myTasklet= new yTasklet();
myTasklet.setStrategy(myCustomStrategy);
return myTasklet;
}
I would like to have the ability to add more strategies without having to modify the code.
The sort answer is yes. This is more general spring/design pattern issue rater then Spring Batch.
The Spring Batch tricky parts are the configuration and understanding scope of bean creation.
Let’s assume all your Strategies implement Strategy interface that looks like:
interface Strategy {
int execute(int a, int b);
};
Every strategy should implements Strategy and use #Component annotation to allow automatic discovery of new Strategy. Make sure all new strategy will placed under the correct package so component scan will find them.
For example:
#Component
public class StrategyA implements Strategy {
#Override
public int execute(int a, int b) {
return a+b;
}
}
The above are singletons and will be created on the application context initialization.
This stage is too early to use #Value("#{jobParameters['strategy']}") as JobParameter wasn't created yet.
So I suggest a locator bean that will be used later when myTasklet is created (Step Scope).
StrategyLocator class:
public class StrategyLocator {
private Map<String, ? extends Strategy> strategyMap;
public Strategy lookup(String strategy) {
return strategyMap.get(strategy);
}
public void setStrategyMap(Map<String, ? extends Strategy> strategyMap) {
this.strategyMap = strategyMap;
}
}
Configuration will look like:
#Bean
#StepScope
public MyTaskelt myTasklet () {
MyTaskelt myTasklet = new MyTaskelt();
//set the strategyLocator
myTasklet.setStrategyLocator(strategyLocator());
return myTasklet;
}
#Bean
protected StrategyLocator strategyLocator(){
return = new StrategyLocator();
}
To initialize StrategyLocator we need to make sure all strategy were already created. So the best approach would be to use ApplicationListener on ContextRefreshedEvent event (warning in this example strategy names start with lower case letter, changing this is easy...).
#Component
public class PlugableStrategyMapper implements ApplicationListener<ContextRefreshedEvent> {
#Autowired
private StrategyLocator strategyLocator;
#Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
Map<String, Strategy> beansOfTypeStrategy = applicationContext.getBeansOfType(Strategy.class);
strategyLocator.setStrategyMap(beansOfTypeStrategy);
}
}
The tasklet will hold a field of type String that will be injected with Strategy enum String using #Value and will be resolved using the locator using a "before step" Listener.
public class MyTaskelt implements Tasklet,StepExecutionListener {
#Value("#{jobParameters['strategy']}")
private String strategyName;
private Strategy strategy;
private StrategyLocator strategyLocator;
#BeforeStep
public void beforeStep(StepExecution stepExecution) {
strategy = strategyLocator.lookup(strategyName);
}
#Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
int executeStrategyResult = strategy.execute(1, 2);
}
public void setStrategyLocator(StrategyLocator strategyLocator) {
this.strategyLocator = strategyLocator;
}
}
To attach the listener to the taskelt you need to set it in your step configuration:
#Bean
protected Step myTaskletstep() throws MalformedURLException {
return steps.get("myTaskletstep")
.transactionManager(transactionManager())
.tasklet(deleteFileTaskelt())
.listener(deleteFileTaskelt())
.build();
}
jobParameters is holding just a String object and not the real object (and I think is not a good pratice store a bean definition into parameters).
I'll move in this way:
#Bean
#StepScope
class MyStategyHolder {
private MyCustomClass myStrategy;
// Add get/set
#BeforeJob
void beforeJob(JobExecution jobExecution) {
myStrategy = (Bind the right strategy using job parameter value);
}
}
and register MyStategyHolder as listener.
In your tasklet use #Value("#{MyStategyHolder.myStrategy}") or access MyStategyHolder instance and perform a getMyStrategy().
#Service
public class LogProcessorServiceImpl {
#Autowired
private static ApplicationConfigurationService applicationConfigurationService;
public static void processPageRequestsLogs() {
if(applicationConfigurationService==null) {
System.out.println("autowire failed");
}
I have the ApplicationConfigurationService service autowired like this all over the place and it works fine. The package of this class is being scanned so that's not the problem. It might be related to the way this particular method is called. I have a servlet that is loaded after all other servlets and it fires of a timer that executes the method above with 60 second delay. I assume all autowiring should be completed.
public class ProcessSchedulerServlet implements javax.servlet.Servlet {
Timer timer=new Timer();
#Override
public void init(ServletConfig arg0) throws ServletException {
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
LogProcessorServiceImpl.processPageRequestsLogs();
}
}, 60*1000, 120*1000);
}
Here's what happens as soon as I true to use ApplicationConfigurationService:
autowire failed
Exception in thread "Timer-1" java.lang.NullPointerException
at com.siteadmin.services.impl.LogProcessorServiceImpl.processPageRequestsLogs(LogProcessorServiceImpl.java:39)
at com.siteadmin.servlets.ProcessSchedulerServlet$1.run(ProcessSchedulerServlet.java:20)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
=== 2012-11-18 ============================================================
See also: How to go about Spring autowiring?
You can't autowire static fields in Spring, this is discussed here
As alternative, if your LogProcessorServiceresides in the root web application context, you can
autowire it with Spring WebApplicationContextUtils utility class.
public class ProcessSchedulerServlet implements javax.servlet.Servlet {
Timer timer=new Timer();
#Autowired
LogProcessorService logProcessorService;
#Override
public void init(ServletConfig arg0) throws ServletException {
WebApplicationContextUtils.getWebApplicationContext(arg0.getServletContext())
.getAutowireCapableBeanFactory().autowireBean(this);
final LogProcessorService svc = this.logProcessorService;
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
svc.processPageRequestsLogs();
}
}, 60*1000, 120*1000);
In general, you should avoid using Java singletons, where using Spring singletons is enough.
Also, if you declared LogProcessorServiceImpl with a #Service annotation, that implies it to be a Spring singleton, so you should not use static fields there at all.
P.S. this answer is about autowiring, it assumes that the idea with TimerTask is correct, in the real apps consider using the Spring Scheduling API