Quartz scheduler thorntail - thorntail

I am new to thorntail. I have integrated quartz in thorntail and able to hit it as REST API. But can I store the scheduler information in context so that scheduler runs once the application is up instead of hitting a URL to run it?
Please correct me if I am wrong .

The question doesn't have much details, but if I understand you correctly, you want to run some code when the application starts. There are at least these 2 ways how to do it:
Using CDI, create an #ApplicationScoped bean with an observer for the #Initialized(ApplicationScoped.class) event:
#ApplicationScoped
public class Initializer {
public void init(#Observes #Initialized(ApplicationScoped.class) Object event) {
...
}
}
This requires the io.thorntail:cdi fraction.
Using EJB, create a #Singleton #Startup EJB and add a #PostConstruct method:
#Singleton
#Startup
public class Initializer {
#PostConstruct
public void init() {
...
}
}
This requires the io.thorntail:ejb fraction.
I assume you already use CDI, so the 1st variant is probably preferable.

Related

How to execute part of the code on Quarkus when starting the application?

Please help me understand that how to execute part of the code on Quarkus when starting the application?
If possible, discard the link or give an example code.
Thanks.
Not sure to understand your question but if you want to execute code at startup, the easiest way is to observe (using #Observes) the StartupEvent with a CDI bean:
#ApplicationScoped
public class AppLifecycleBean {
private static final Logger LOGGER = Logger.getLogger("ListenerBean");
void onStart(#Observes StartupEvent ev) {
LOGGER.info("The application is starting...");
}
void onStop(#Observes ShutdownEvent ev) {
LOGGER.info("The application is stopping...");
}
}
You can find more details in our documentation if you need a better understanding of the Quarkus application lifecycle:
https://quarkus.io/guides/lifecycle#listening-for-startup-and-shutdown-events
There is an #Startup annotation for Quarkus that will instantiate a service upon startup. It simply automates the listening of the StartupEvent:
For each bean annotated with #Startup a synthetic observer of StartupEvent is generated. The default priority is used.
Works well.
Quarkus #Startup annotation

How to pass a POJO to the SpringBoot application run method?

I have this
#Bean public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
// use a lambda expression to define a CommandLineRunner
return args -> {
... work ...
};
}
which is invoked like this
SpringApplication app = new SpringApplication(MyApp.class);
app.run(args); // perform configuration magic and invoke the above lambda function
This works great as long as the application was only used from the CLI. Now, the application is going through some refactoring to support a new run-time platform, and now I would like to do this:
app.run(complexOject); // pseudo-code, no such method in SpringApplication
i.e. I need to pass an ComplexObject to the application, while still preserving all the magic auto-configuration.
How can this be accomplished? Solutions with the least amount of code change are preferred.
The refactoring steps to enable a CommandLineRunner to receive arbitrary parameters is roughly as follows:
Move the guts (the ... work ... part) of the commandLineRunner method to a new method in a new bean class e.g. #Component public class GenericRunner { public void run(String ... args) ... }.
This is the most important step: Delete the original CommandLineRunner #Bean definition in its entirety. This will cause the application's run() method to exit after performing configuration.
Replace the app.run(args); invocation with the following
ConfigurableApplicationContext ctx = app.run(); // oh yeah
GenericRunner runner = ctx.getBean(GenericRunner.class);
runner.run(args);
Re-run all tests, commit the code changes.
The actual refactoring is now trivial: modify the runner.run(args) call at will. This is just a straight call into the GenericRunner POJO and is free of SpringBoot rules and limitations.
SpringApplication class obviously doesn't have a method that gets this output stream, its an entry point to the complicated by very powerful spring boot application loading process.
If the goal is to store the log of the application consider logging configuration rather than using output streams.
Otherwise please describe the requirement, what is the purpose of this output stream and I'll do my best to update this answer.
Update:
SpringApplication starts up an application context that is used as a registry for spring beans in the application.
So the most "spring friendly solution is to define a ComplexObject to be a spring bean, so that it will be injected into other beans that might need it.
This will work great if this bean can be created during the application startup.
Example:
class ComplexObject {...}
class ServiceThatMaintainsAReferenceOnObject {
private ComplexObject complexObject;
// all arg constructor
}
#Configuration
class SpringConfiguration {
#Bean
public ComplexObject complexObject() {
return new ComplexObject();
}
#Bean
public ServiceThatMaintainsAReferenceOnObject service(ComplexObject complexObject) {
return new ServiceThatMaintainsAReferenceOnObject(complexObject);
}
}
Now, if this complex object has to be created outside the spring application, maybe you need to pass it to some bean method as a parameter, after the application context is created. This can also be a case in the question, although it's definitely not a Spring way to do things.
Here is an example:
class ComplexObject {}
class Service {
void foo(ComplexObject complexObject);
}
#Configuration
class MyConfiguration {
#Bean
public Service service() {
return new Service();
}
}
// inside the main class of the application:
SpringApplication app = ...
ComplexObject complexObject = ... // get the object from somewhere
ApplicationContext ctx = app.run(args);
// by this time, the context is started and ready
Service service = ctx.getBean(Service.class);
service.foo(complexObject); // call the method on bean managed by spring
All in all, usually the second approach is not a regular use case of spring application, although its kind of feels like you're looking for something like this in the question.
All-in-all I think you should learn and understand how Spring works in a nutshell, and what exactly the ApplicationContext is to provide the best solution (I'm sorry for mentioning this, I said so because from the question it looks like you haven't really worked with Spring and don't really understand what does it do and how does it manage the application).

Where should I place the application logic of non-web, non-batch Spring Boot app?

I'm trying to start my non-web/non-batch Spring boot application properly.
However, if I place the main tasks in a CommandLineRunner it also gets triggered while running the tests. Running the tasks as batch job will work, but my task doesn't follow batch job semantics.
Is extending SpringApplication class and putting the logic in run() method after super() call the standard way?
If you annotate your CommandLineRunner bean with the #Profile annotation, you can tell Spring to only create the bean when running with (or without) certain profiles, for example:
#Component
#Profile("autorun")
public class JobRunner implements CommandLineRunner {
// ...
}
As long as you don't use those profile when testing, it should not be invoked. You can then run the application using the -Dspring.profiles.active=autorun parameter.
You can create a separate Component class and assign a profile
#Component
#Profile("!test")
public class RunApplication implements CommandLineRunner {
#Override
public void run(String... args) throws IOException {
//Your code here
}
}
This class will only be initialized when the spring.profiles.active variable is not equal to test
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/CommandLineRunner.html

init method in jersey jax-rs web service

I'm new with jax-rs and have build a web service with jersey and glassfish.
What I need is a method, which is called once the service is started. In this method I want to load a custom config file, set some properties, write a log, and so on ...
I tried to use the constructor of the servlet but the constructor is called every time a GET or POST method is called.
what options I have to realize that?
Please tell, if some dependencies are needed, give me an idea how to add it to the pom.xml (or else)
There are multiple ways to achieve it, depending on what you have available in your application:
Using ServletContextListener from the Servlet API
Once JAX-RS is built on the top of the Servlet API, the following piece of code will do the trick:
#WebListener
public class StartupListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
// Perform action during application's startup
}
#Override
public void contextDestroyed(ServletContextEvent event) {
// Perform action during application's shutdown
}
}
Using #ApplicationScoped and #Observes from CDI
When using JAX-RS with CDI, you can have the following:
#ApplicationScoped
public class StartupListener {
public void init(#Observes
#Initialized(ApplicationScoped.class) ServletContext context) {
// Perform action during application's startup
}
public void destroy(#Observes
#Destroyed(ApplicationScoped.class) ServletContext context) {
// Perform action during application's shutdown
}
}
In this approach, you must use #ApplicationScoped from the javax.enterprise.context package and not #ApplicationScoped from the javax.faces.bean package.
Using #Startup and #Singleton from EJB
When using JAX-RS with EJB, you can try:
#Startup
#Singleton
public class StartupListener {
#PostConstruct
public void init() {
// Perform action during application's startup
}
#PreDestroy
public void destroy() {
// Perform action during application's shutdown
}
}
If you are interested in reading a properties file, check this question. If you are using CDI and you are open to add Apache DeltaSpike dependencies to your project, considering having a look at this answer.

Event Listeners in spring is called twice

I am an issue with Spring Event Listeners In my Web app, Any immediate help will be appreciated.
Event Listeners is registered and called twice, If I have cyclic dependency.
I have service class, this has #transaction annotation on another methods
#Service(PBSTaskService.BEAN_NAME)
public class PBSTaskServiceImpl extends StandardServiceImpl<ITask> implements PBSTaskService,ApplicationListener<SurveyDefinitionPublishedEvent>
{
#Autowired
private AutoSelectTaskSliceRouteSyncService autoSelectTaskSliceRouteSyncService; // CYCLIC Dependency
#Override
public void onApplicationEvent(SurveyDefinitionPublishedEvent event)
{
System.out.println("PBSTSImpl"); // THIS IS CALLED TWICE
}
... Other method with #Transaction Annotation
}
#Service(AutoSelectTaskSliceRouteSyncService.BEAN_NAME)
public class AutoSelectTaskSliceRouteSyncServiceImpl implements AutoSelectTaskSliceRouteSyncService
{
#Autowired private PBSTaskService pbsTaskService; // CYCLIC dependency
}
Now If I remove AutoSelectTaskSliceRouteSyncService dependency from First Class, OnApplicationEvent is called once, else twice.
I debugged and found out that
SimpleApplicationEventMulticaster.getApplicationListeners(myEvent) : Has two proxy object, one wrapped with Cglib and another default one. But it has two only in case if it has cyclic dependency. If I remove Cyclic dependency, it has only one proxy object and that one is enahnces by CGLIB.
my Tx annotation :
I had tried it with proxy-target-class="true or false" but no luck.
You may want to have a look on
https://jira.springsource.org/browse/SPR-7940?focusedCommentId=98988&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-98988
Since Spring 4.2 you can do away with implementing ApplicationListener and use the new #EventListener annotation on methods in any managed bean. This should help you avoid any conflicts.
Below is an example from https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2
#Component
public class MyListener {
#EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
...
}
}
ApplicationEvent Listeners are called twice at many more places in our web app. This is one of scenarios that we caught up.
Reason :
Listeners are registered twice. Two proxy are returned wrapped over one instance of listeners. Proxy returned are 1. Dynamic Jdk Interface proxy 2. Cglib Proxy, when we have #transactions annotations.
To recreate these three point are must:
Your listeners must implements ApplicationListener 2. Your listeners must have cyclic dependency with another class 3.Your listeners must have one method annotated with #Transaction.
I have created a separate project where I am able to reproduce it with spring and hibernate. If 2 and 3 are not present together, then we are safe.
Solution
I tried many tweaks with spring and transaction configuration but no luck. Then finally with my demo project when I moved the transaction code to another class, so that the listeners do not have any #transaction annotations then it worked for me.
In Spring classes anotated with #Service or #Component which implement the ApplicationListener interface are going to receive duplicate events. To resolve the issue, to only receive single events, just remove the #Service or #Compontent annotation.
In a case of circular dependency between Spring beans, Spring Beans machinery might (under certain circumstances) place two versions of a same bean, the bean itself and its Advised wrapper into the list of ApplicationListeners handled by an ApplicationEventMulticaster.
You could, however, implement your custom ApplicationEventMulticaster and fix this bug (it looks like a bug to me).
In a snippet below a custom implementation subclasses Spring's SimpleApplicationEventMulticaster, ignores non-Advised duplicate of a bean, and leaves Advised version of it in the list of ApplicationListeners (most likely you would want an Advised version of your onApplicationEvent method to be called - in a case it is annotated with #Transactional or AOP-advised, but if you need otherwise, the change of algorithm is trivial)
#Component
public class AdviceAwareApplicationEventMulticaster extends SimpleApplicationEventMulticaster {
#Override
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
Map<ApplicationListener<?>, ApplicationListener<?>> listenersByNakedInstances = new LinkedHashMap<>();// because superclass returns sorted listeners
Collection<ApplicationListener<?>> applicationListeners = super.getApplicationListeners(event, eventType);
for (ApplicationListener<?> listener : applicationListeners) {
boolean advised = false;
ApplicationListener<?> nakedListener = null;
if (listener instanceof Advised) {
try {
nakedListener = (ApplicationListener<?>) ((Advised)listener).getTargetSource().getTarget();
} catch (Exception e) {
// TODO
}
advised = true;
} else
nakedListener = listener;
if (advised || !listenersByNakedInstances.containsKey(nakedListener))
listenersByNakedInstances.put(nakedListener, listener);
}
return listenersByNakedInstances.values();
}
}
You don't need to anyhow make your custom implementation known to Spring, it's enough to have it as a Spring bean and Spring Application Context will pick it up.
Also, don't forget that if there are more one Spring Application Contexts in the application, your Listener might be called for each of those, but it's altogether different story.
I was running into the same issue with one of my services, created another listner with the same event that was only called once.
So what #SimonH wrote is not always the case, only in some circumstances I could not reproduce:
In Spring classes anotated with #Service or #Component which implement the ApplicationListener interface are going to receive duplicate events.
In my case this lead to a double call of the onApplicationEvent method.
#Service
public class TestClass implements ApplicationListener<MyEvent>{
#Override
public void onApplicationEvent(MyEvent event){
// called twice
}
}
Instead of the code above, I could solve it by creating the Event Listener as an inner class and then call the event method of the parent.
#Service
public class TestClass {
#Component
private class MyListener implements ApplicationListener<MyEvent> {
#Override
public void onApplicationEvent(MyEvent event) {
TestClass.this.onApplicationEvent(event);
}
}
public void onApplicationEvent(MyEvent event){
//Have fun with a single event here
}
}

Resources