I have started a Quarkus project and i have there 2 tables, i am trying to run a Method immediately after deploying, In the method i use Entitymanger to save some results in the database.
In pure Jakarta EE, you could an EJB and annotate it with #Startup. But Since quarkus uses CDI.
#ApplicationScoped
public class StartApp {
private static final String PERSISTENCE_UNIT_NAME = "Employee";
public void init(#Observes #Initialized(ApplicationScoped.class) Object init) {
EntityManagerFactory factory =
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
Directory directory = new Directory("/some/info", true, false, ".xml");
em.persist(directory);
em.close();
}
}
How can i do that!? some guess !
I think what you need is this:
#ApplicationScoped
class StartApp {
void startup(#Observes StartupEvent event) {
// Do whatever needs to be done.
}
}
More information and options can be found on the very well documented quarkus pages. https://quarkus.io/guides/cdi-reference#startup-event
Ps. don't forget about your transactions and maybe take a look at Hibernate ORM.
Related
I´m in trouble with old EJBs that i have no control over the source code, there is no source code, only the ejb jar. They were born in weblogic 5.
We are migrating to weblogic 12c and When i deploy then, the EJB checker give me some compliance ejb errors.
I have been investigating the class ...
[Loaded weblogic.ejb.container.compliance.EJBComplianceChecker from ......product/Oracle_Home/wlserver/modules/com.oracle.weblogic.ejb.jar]
Decompiled and I have found this ....
public final class EJBComplianceChecker
extends BaseComplianceChecker
implements ComplianceChecker, PlatformConstants
{
public static final boolean isNeedCheck = Boolean.getBoolean("ignoreEJBChecker");
static final ComplianceChecker INSTANCE = new EJBComplianceChecker();
public void checkDeploymentInfo(DeploymentInfo di)
throws ErrorCollectionException
{
if (isNeedCheck) {
return;
}
Set<Class<?>> deploymentInfoCheckers = new HashSet();
Object interceptorChecker = null;
Object[] relationshipCheckers = null;
for (BeanInfo bi : di.getBeanInfos()) ....
I think this might be some kind of deployment configuration, but i have found no information about it...
public static final boolean isNeedCheck = Boolean.getBoolean("ignoreEJBChecker");
it controls the value and let it check or not.
if (isNeedCheck) {
return;
}
thanks
that seems to work. Know i can not see the error.
Thank for all Emmanuel
I want to read text data fixtures (CSV files) at the start on my application and put it in my database.
For that, I have created a PopulationService with an initialization method (#PostConstruct annotation).
I also want them to be executed in a single transaction, and hence I added #Transactional on the same method.
However, the #Transactional seems to be ignored :
The transaction is started / stopped at my low level DAO methods.
Do I need to manage the transaction manually then ?
Quote from legacy (closed) Spring forum:
In the #PostConstruct (as with the afterPropertiesSet from the InitializingBean interface) there is no way to ensure that all the post processing is already done, so (indeed) there can be no Transactions. The only way to ensure that that is working is by using a TransactionTemplate.
So if you would like something in your #PostConstruct to be executed within transaction you have to do something like this:
#Service("something")
public class Something {
#Autowired
#Qualifier("transactionManager")
protected PlatformTransactionManager txManager;
#PostConstruct
private void init(){
TransactionTemplate tmpl = new TransactionTemplate(txManager);
tmpl.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
//PUT YOUR CALL TO SERVICE HERE
}
});
}
}
I think #PostConstruct only ensures the preprocessing/injection of your current class is finished. It does not mean that the initialization of the whole application context is finished.
However you can use the spring event system to receive an event when the initialization of the application context is finished:
public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
public void onApplicationEvent(ContextRefreshedEvent event) {
// do startup code ..
}
}
See the documentation section Standard and Custom Events for more details.
As an update, from Spring 4.2 the #EventListener annotation allows a cleaner implementation:
#Service
public class InitService {
#Autowired
MyDAO myDAO;
#EventListener(ContextRefreshedEvent.class)
public void onApplicationEvent(ContextRefreshedEvent event) {
event.getApplicationContext().getBean(InitService.class).initialize();
}
#Transactional
public void initialize() {
// use the DAO
}
}
Inject self and call through it the #Transactional method
public class AccountService {
#Autowired
private AccountService self;
#Transactional
public void resetAllAccounts(){
//...
}
#PostConstruct
private void init(){
self.resetAllAccounts();
}
}
For older Spring versions which do not support self-injection, inject BeanFactory and get self as beanFactory.getBean(AccountService.class)
EDIT
It looks like that since this solution has been posted 1.5 years ago developers are still under impression that if a method,
annotated with #Transactional, is called from a #PostContruct-annotated method invoked upon the Bean initialization, it won't be actually executed inside of Spring Transaction, and awkward (obsolete?) solutions get discussed and accepted instead of this very simple and straightforward one and the latter even gets downvoted.
The Doubting Thomases :) are welcome to check out an example Spring Boot application at GitHub which implements the described above solution.
What actually causes, IMHO, the confusion: the call to #Transactional method should be done through a proxied version of a Bean where such method is defined.
When a #Transactional method is called from another Bean, that another Bean usually injects this one and invokes its proxied (e.g. through #Autowired) version of it, and everything is fine.
When a #Transactional method is called from the same Bean directly, through usual Java call, the Spring AOP/Proxy machinery is not involved and the method is not executed inside of Transaction.
When, as in the suggested solution, a #Transactional method is called from the same Bean through self-injected proxy (self field), the situation is basically equivalent to a case 1.
#Platon Serbin's answer didn't work for me. So I kept searching and found the following answer that saved my life. :D
The answer is here No Session Hibernate in #PostConstruct, which I took the liberty to transcribe:
#Service("myService")
#Transactional(readOnly = true)
public class MyServiceImpl implements MyService {
#Autowired
private MyDao myDao;
private CacheList cacheList;
#Autowired
public void MyServiceImpl(PlatformTransactionManager transactionManager) {
this.cacheList = (CacheList) new TransactionTemplate(transactionManager).execute(new TransactionCallback(){
#Override
public Object doInTransaction(TransactionStatus transactionStatus) {
CacheList cacheList = new CacheList();
cacheList.reloadCache(MyServiceImpl.this.myDao.getAllFromServer());
return cacheList;
}
});
}
The transaction part of spring might not be initialized completely at #PostConstruct.
Use a listener to the ContextRefreshedEvent event to ensure, that transactions are available:
#Component
public class YourService
implements ApplicationListener<ContextRefreshedEvent> // <= ensure correct timing!
{
private final YourRepo repo;
public YourService (YourRepo repo) {this.repo = repo;}
#Transactional // <= ensure transaction!
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
repo.doSomethingWithinTransaction();
}
}
Using transactionOperations.execute() in #PostConstruct or in #NoTransaction method both works
#Service
public class ConfigurationService implements ApplicationContextAware {
private static final Logger LOG = LoggerFactory.getLogger(ConfigurationService.class);
private ConfigDAO dao;
private TransactionOperations transactionOperations;
#Autowired
public void setTransactionOperations(TransactionOperations transactionOperations) {
this.transactionOperations = transactionOperations;
}
#Autowired
public void setConfigurationDAO(ConfigDAO dao) {
this.dao = dao;
}
#PostConstruct
public void postConstruct() {
try { transactionOperations.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(final TransactionStatus status) {
ResultSet<Config> configs = dao.queryAll();
}
});
}
catch (Exception ex)
{
LOG.trace(ex.getMessage(), ex);
}
}
#NoTransaction
public void saveConfiguration(final Configuration configuration, final boolean applicationSpecific) {
String name = configuration.getName();
Configuration original = transactionOperations.execute((TransactionCallback<Configuration>) status ->
getConfiguration(configuration.getName(), applicationSpecific, null));
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
}
}
How to get the Persistence Unit Name dynamically?
For example in below example,I am hard coding unitName to application_openjpa, but I want to give it dynamically as unitName=#{unitName} so if I have different project uses the entity jar, but can use its own persistence.xml file
#PersistenceContext(unitName="application_openjpa")
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
Since an application normally have limited number of persistence units, how about create two setter methods and annotate it with different unitName attribute, eg:
#PersistenceContext(unitName="testEM")
public void setTestEntityManager(EntityManager testEM) {
this.testEM = testEM;
}
#PersistenceContext(unitName="prodEM")
public void setProdEntityManager(EntityManager prodEM) {
this.prodEM = prodEM;
}
Then you can choose between testEM and prodEM dynamically ?
I have migrated my app from Glassfish 2.2.1 to JBoss AS 6.
Previously i have a generic class for lookup the ejbs, Below is the code:
public class BeanUtil {
private static InitialContext ctx;
public static <T> T create(Class<T> type){
try {
ctx = new InitialContext();
return (T)ctx.lookup(type.getName());
} catch (NamingException e) {
e.printStackTrace();
}
return null;
}
}
The above class works fine for lookup in glassfish.
But after migrating the code to JBoss AS 6. I always get javax.naming.NameNotFoundException
Below is one of my ejb class.
#Remote
public interface OperationPerformed {
public void addRandomNo(String randomNos);
}
#Stateless
#Remote(OperationPerformed.class)
public class OperationPerformedImpl implements OperationPerformed {
public void addRandomNo(String randomNos) {
}
}
If i give the complete jndi name which jboss made during deployment of my app, then i can easily lookup the same. But i want generic code for lookup.
Below is the code which i invoke for lookup a bean:
OperationPerformed operationPerformed =
BeanUtil.create(OperationPerformed.class);
Please suggest if i am doing something wrong.
I think you can convert class name to jndi name and look it up normally
Some suggestions:
It's quite unusual to use #Remote annotation on interface and implementation at the same time. Remove this annotation from your stateless bean, it's redundant.
I agree with other posters:
don't use remote interface for local lookups and injections, create another interface and mark it with #Local.
when it comes to JVM-local operations #EJB injection is vastly supperior comparing to manual JNDI lookup (see responses to http://stackoverflow.com/questions/12681436/ejb-annotation-vs-jndi-lookup and similar questions on SO).
To sum it all:
create OperationPerformedLocal.java :
#Local
public interface OperationPerformedLocal {
public void addRandomNo(String randomNos);
}
modify your SLSB:
#Stateless
public class OperationPerformedImpl implements OperationPerformedLocal, OperationPerformed {
public void addRandomNo(String randomNos) {
}
}
and use injection rather than jndi lookup whenever possible:
#EJB
private OperationPerformedLocal operationPerformed;
In case of WAR modules some CDI #Injection magic should work, but I haven't got any real experience with it yet.
Now, if you insist on using plain JNDI lookups and want them to be as generic as possible, I came up with this solution:
public class BeanUtil {
private static InitialContext ctx;
public static <T, C> T create(Class<C> implType, Class<T> interfaceType) {
try {
ctx = new InitialContext();
return (T)ctx.lookup(implType.getSimpleName()+"/local");
} catch (NamingException e) {
e.printStackTrace();
}
return null;
}
}
you can use it this way:
try {
OperationPerformedLocal operationPerformed =
BeanUtil.create(OperationPerformedImpl.class, OperationPerformedLocal.class);
operationPerformed.addRandomNo("123");
} catch (Exception e) {
e.printStackTrace();
}
It's ugly I know, I'm kind of embarassed posting it.
It's not portable, forces you to know interface and implementation classes and "/local" part is hardcoded making it even more ugly ::sigh::.
Placing EJB-JAR(s) into EAR can complicate things a little bit further, jndi-name will be prefixed with EAR name:
return (T)ctx.lookup("earName/" + implType.getSimpleName() + "/local");
Moreover, it'll probably break if SLSB has changed name i.e. #Stateless(name="someNewName").
Well, I'm using Quartz to schedule some jobs that I need in my application. But, I need some way to access a Stateful SessionBean on my Job. I knew that I can't inject it with #EJB. Can anyone help me?
Thanks.
I used the EJB3InvokerJob to invoke the methods of my EJB. Then I created my jobs that extends the EJB3InvokerJob, put the parameters of what EJB and method it should call and then call the super.execute().
The EJB3InvokerJob can be found here: http://jira.opensymphony.com/secure/attachment/13356/EJB3InvokerJob.java
My Job is looking like this:
public class BuscaSistecJob extends EJB3InvokerJob implements Job{
private final Logger logger = Logger.getLogger(this.getClass());
#Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDataMap dataMap = jobExecutionContext.getMergedJobDataMap();
dataMap.put(EJB_JNDI_NAME_KEY, "java:app/JobService");
dataMap.put(EJB_INTERFACE_NAME_KEY, "br.org.cni.pronatec.controller.service.JobServiceLocal");
dataMap.put(EJB_METHOD_KEY, "buscaSistec");
Object[] arguments = new Object[1];
arguments[0] = jobExecutionContext.getTrigger().getStartTime();
dataMap.put(EJB_ARGS_KEY, arguments);
Class[] argumentTypes = new Class[1];
argumentTypes[0] = Date.class;
dataMap.put(EJB_ARG_TYPES_KEY, argumentTypes);
super.execute(jobExecutionContext);
}
}
And my EJB is like this:
#Stateless
#EJB(name="java:app/JobService", beanInterface=JobServiceLocal.class)
public class JobService implements JobServiceLocal {
#PersistenceContext
private EntityManager entityManager;
#Resource
private UserTransaction userTransaction;
#Override
public void buscaSistec(Date dataAgendamento) {
// Do something
}
I expect to help someone.
A simple solution would be to lookup the EJB via JNDI in the Job implementation.
final Context context = new InitialContext();
myService= (MyService) context
.lookup("java:global/my-app/myejbmodule-ejb/MyService");
I have done this in a current application I am developing on Glassfish 3.1.
you can do that simply by lookup the EJB via JNDI in the Job implementation. In particular, the JNDI name will be:
mappedName#name_of_businessInterface
where name_of_businessInterface is the fully qualified name of the business interface of this session bean. For example, if you specify mappedName="bank" and the fully qualified name of the business interface is com.CheckingAccount, then the JNDI of the business interface is bank#com.CheckingAccount.
Code Example:
Context context = new InitialContext();
MyService myService= (MyService) context.lookup("MyService#com.test.IMyService");