I have a custom API that I am working on that has to go through a variety of steps to authenticate and set itself up. That setup being oAuth, HTTP Request, and Websockets. I have the setup done fine and all that working, but what I am having trouble after.
When I implement and initialize my API in the java program the methods like api.methodHandler.sendMessage("Registering Events"); are running before the API finishes setting itself up.
I have tried using wait, sleeps, etc.
api.setupAPI(clientid, clientSecret, cid, uid, null);
api.methodHandler.sendMessage("Registering Events");
api.eventManager.registerEvent(new EventHandler());
No errors, but the methods are just running before they should.
There is a good site that explains your options for solving this problem: Running Setup Data on Startup in Spring. But to give you few options: You can annotate your method
#EventListener(ApplicationReadyEvent.class)
#Order(20)
public void runMyLogicAfterAppIsInitialized() {
...
}
The #Order annotation is not necessary but if you have several methods annotated with #EventListener you can control their execution order
Or a bit older way is to implement ApplicationListener interface
#Component
public class StartupApplicationListenerExample implements
ApplicationListener<ContextRefreshedEvent> {
private static final Logger LOG
= Logger.getLogger(StartupApplicationListenerExample.class);
public static int counter;
#Override public void onApplicationEvent(ContextRefreshedEvent event) {
LOG.info("Increment counter");
counter++;
}
}
Related
Here is my problem.
I have a class implements Runnable, and it is a daemon thread, which will be permanently alive during the application lifecycle.
Now I want to perform a function just like AOP enhancement to enhance this Runnable class.
It was quite easy to have that pointcut if the class is annotated with #Service or #Component. But now it is a class implememts the Runnable interface so I have not yet find any possible ways to do so without any intrusion to the original code.
Here below is my testing code:
this is the parent interface of my daemon thread
public interface MessageRunnable extends Runnable {
void doConsume();
}
one of the working thread:
#Slf4j
public class MyDaemonThread implements MessageRunnable{
#Override
public void run() {
log.info("now in run function,ready to call doConsume...");
while(true){
log.info("I m still alive...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
doConsume();
}
}
#Override
public void doConsume() {
log.info("doConsume was called...");
}
}
And here is the simple test:
#Component
public class TestComponent {
private MyDaemonThread testThread;
#PostConstruct
public void init(){
if(testThread==null){
testThread=new MyDaemonThread();
new Thread(testThread).start();
}
}
}
After running the application.
I can see the log is printing well, but now if I want to add a function to print now I'm in the aspect method before the doConsume function was invoked, I don't have any idea to do so without any intrude to my source code, it is acceptable to add codes ,but no modifications were allowed at all.
I wonder if there is any possible ways to let spring handle this daemon thread, then it is easy to do an aspect point cut. Otherwise, I have to change the code to add a proxy method and an interceptor do achieve the goal....
First of all , MyDaemonThread instance is not a spring container managed bean. The code uses new keyword to create the instance. Spring AOP can only advise a spring bean.
Even if the MyDaemonThread is made a spring bean , it is not possible to advise doConsume() using Spring AOP with the current code ( OP mentions no modifications are allowed ).
From the reference documentation
Due to the proxy-based nature of Spring’s AOP framework, calls within
the target object are, by definition, not intercepted.
I have a Springboot restful webapp and I'm using #Async to run a method to do processing on some data. A request comes a Controller.java class.and I return a response in main thread like "Request has been received.." while a new thread gets spun up and does the processing.
It was working fine but I come back to it today after the weekend and it no longer creates new threads. I confirmed async pieces of code have not been modified. I have not seen any scheduled maintenance for my remote desktop, checked my windows log to see if there were any events that might cause my workspace to be out of sync or something but haven't found anything.
I've looked all over SO and only found problem/solutions when things are missing like annotations or no Async Configurations..etc all of which i can confirm i have implemented, as I said it was working previously.
Has anyone ever encountered this behavior where an #Async annotation suddenly stops working?
Modified code snippet below.
//a java file an impl class
#Repository
public class InterfaceImpl implements Interface {
#Autoriwed
#Qualifier("Qualifier")
Interface service;
//iforget how its implemented at work something like this to illustrate
#PostMapping(application/process)
public ResponseEntity processdata(#RequestBody String lotsofdata) {
ResponseEntity entity = new ResponseEntity();
service.asyncMethod();
return Status.OK.entity("Request received. Processing.").build();
}
}
//a java file an impl class
#Service(value = "Qualifier")
public class InterfaceImpl implements Interface {
#Override
#Async("processExecutor")
public void asyncMethod(){
# do some heavy stuff
}
}
//a java file--an interface for above class
public interface Interface {
void asyncMethod();
}
//a pretty boilerplate asyncconfig java file
#Configuration
#EnableAsync
public class AsyncConfig implements AsyncConfigurer {
//to catch exceptions in thread
#Autowired
CustomAsyncExceptionHandler asyncExceptionHandler;
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return asyncExceptionHandler;
}
#Bean(name="processExecutor")
#Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("Async-");
threadPoolTaskExecutor.setCorePoolSize(3);
threadPoolTaskExecutor.setMaxPoolSize(3);
threadPoolTaskExecutor.setQueueCapacity(10);
threadPoolTaskExecutor.afterPropertiesSet();
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
}
Is there something in Springtool Suite or with Tomcat that maybe needs a refresh or something? I'm pulling my hair out because of it. I haven't removed any dependencies out of my pom. As i said it was working previously and I'm kind of looking for things that others might have seen along similar lines of behavior and maybe what they looked at to diagnose a cause. I have not seen any bugs reported on this in my searches but could it be a potential bug?
Thanks.
In what circumstances CommandLineRunner is preferred instead of writing additional code in the main method of SpringBoot application.
I understand that CommandLineRunner gets executed before main gets completed.
In simple cases, there is no difference.
But if the code need to access features provided by spring, such as ioc or only interface repositories/services, you need to wait for the complete application startup. And the call of the overrided run method after completion is garanteed.
Besides, CommandLineRunner has other advantages:
Can be implemented multiple times
The capability to start any scheduler or log any message before application starts to run
I have used it to decouple code. Instead of placing a bunch of code into main method, the CommandLineRunner lets you distribute it more evenly around the codebase. It really depends on what kind of flags you are passing in and why you need to pass them in. Spring offers a lot of flexibility for you to get the job done in the easiest way.
For a full on command line tool, you can decouple initialization and config a little bit by dividing your code between init and core behavior.
A spring boot server can overwrite configuration based on args passed in from the command line.
I would suggest all time time. It adds a lot of flexibility to your "bootstrapping code".
1) For example, command line runners are spring #Beans, so you can activate/deactivate them at run-time.
2) You can use them in an ordered fashion by appending the #Order annotation
3) You can unit test them just like regular classes
4) You can inject dependencies into them. Each runner can then have its own dependencies.
All of the above are more difficult, if not impossible to achieve if you add all your bootstrapping logic in the main() method of the Spring Application class.
Hope my answer helps,
Cheers
I haven't found any good reason for using it over just writing code after starting the application.
The only thing I can think of is that the command line runners are called before any SpringApplicationRunListeners have #finished called.
I have seen people use them to perform main application logic, but I think this is an antipattern.
One of the annoying things about doing so is that the application start timer is still running and when the task completes you will see a log entry like Started DemoApplication in 5.626 seconds (JVM running for 0.968).
It's confusing to see a message about your application starting despite, in reality it having just finished.
I encountered a scenario where i had to keep a certain data from the db loaded into the cache before the method was hit from the controller end point the first time. In this scenario it was desirable to hit the method for populating the cache using the run method after extending CommandLineRunner class so that before the application even starts up the data is already available in the cache.
I use this to populate my Default Data. I usually create ApplicationInitializer class that extends CommandLineRunner.
I have methods like createDefaultUser(), createDefaultSytemData() etc.
This way I do not rely on sql files to populate database for me. :)
ApplicationRunner and CommandLineRunner:
two of them can execute some custom code before your application finished starting up.
ComandLineRunner:
#Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(CommandLineAppStartupRunner.class);
#Override
public void run(String...args) throws Exception {
logger.info(Arrays.toString(args));
}
}
you can get the args directly
ApplicationRunner:
#Component
public class AppStartupRunner implements ApplicationRunner {
private static final Logger logger = LoggerFactory.getLogger(AppStartupRunner.class);
#Override
public void run(ApplicationArguments args) throws Exception {
logger.info(args.getOptionNames());
}
}
ApplicationRunner has many methods to get params
ComandLineRunner can get params directly
if you custom two runner class, you can use annotation #Order to Specify the order of execution
public class Phone {
#Autowired
BeanExample beanExample;
public void print(){
beanExample.fn();
}
}
public class BeansCreatorClass {
#Bean
public BeanExample getBeanExample(){
return new BeanExample();
}
#Bean
public Phone getPhone(){
return new Phone();
}
}
#SpringBootApplication
public class SpringBootRunnerConfigurationPropertiesApplication implements CommandLineRunner, ApplicationRunner {
public static void main(String[] args){
SpringApplication.run(SpringBootRunnerConfigurationPropertiesApplication.class, args);
System.out.println("==== spring boot commandLine is running === ");
// beans creator class is the class contains all beans needed
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansCreatorClass.class);
Phone phone = applicationContext.getBean(Phone.class);
phone.print();
}
// commandLineRunner
public void run(String... args) throws Exception {
System.out.println("=== commandLine Runner is here ==== ");
}
// application runner
#Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("=== application runner is here ====");
}
}
I mostly use CommandLineRunner to:
Apply initial migrations
Run a code that is independent of REST/SOAP calls.
Here is my abstract class which starts Jersey with given Spring context:
public abstract class AbstractJerseyTest extends JerseyTest {
public void setUp() throws Exception {
super.setUp();
}
#AfterClass
public void destroy() throws Exception {
tearDown();
}
#Override
protected URI getBaseUri() {
return URI.create("http://localhost:9993");
}
#Override
protected Application configure() {
RestApplication application = new RestApplication();
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
properties.put("contextConfigLocation", "classpath:spring-context-test.xml");
application.setProperties(properties);
application.register(this);
return application;
}
}
So, the problem is that I need to access Spring bean from my test to populate database with some data.
Jersey version is 2.6
Also I found a similar question here
But it's related to Jersey 1.x so it doesn't work for Jersey 2.x
Could anyone point me in the right direction?
Solution was really simple.
I added:
#Autowired
private Repository repository;
to the AbstractJerseyTest and this field was automatically autowired during test startup. I don't know details about how it works, but it seems that when I register instance of the test in REST application
application.register(this);
it automatically autowires all beans in the test.
Normally in your case, I'd just say work with mocks, but there are cases where you may need to expose the services in the test class.
To do this without any "ugly hacks", you will need to get a handle on the ServiceLocator (which is analogous to Spring's ApplicationContext). When the Jersey app boots up, all the Spring services from the ApplicationContext are put into the ServiceLocator through HK2's Spring bridge.
The problem is JerseyTest does not expose the ServiceLocator in any way. The only way I can think of to get a hold of it, is to create your own TestContainerFactory, and create the ApplicationHandler, which exposes the ServiceLocator.
Trying to implement your own TestContainerFactory is not a walk in the park, if you don't know what you're doing. The easiest thing to do is just look at the source code for Jersey's InMemoryTestContainerFactory. If you look at the constructor for the inner class InMemoryTestContainer, you will see it creating the ApplicationHandler. This is how you can expose the ServiceLocator, through the appHandler.getServiceLocator().
So if you copied that class, and exposed the ServiceLocator, you could create your JerseyTest extension, and call the ServiceLocator.inject(Object) method to inject the test class.
public abstract class AbstractServiceLocatorAwareJerseyTest extends JerseyTest {
private final ServiceLocatorAwareInMemoryTestContainerFactory factory
= new ServiceLocatorAwareInMemoryTestContainerFactory();
private ServiceLocator locator;
#Override
public TestContainerFactory getTestContainerFactory() {
return factory;
}
#Before
#Override
public void setUp() throws Exception {
super.setUp();
this.locator = factory.getServiceLocator();
if (injectTestClass()) {
this.locator.inject(this);
}
}
public boolean injectTestClass() {
return true;
}
public ServiceLocator getServiceLocator() {
return locator;
}
}
And if for any reason you needed it, the ServiceLocator also has the ApplicationContext, which you could also expose to your test class if needed.
I put together a GitHub project, with a complete implementation, with tests if you want to take a look at it.
UPDATE
Though the OP's answer to this question works, I believe the fact that it works, is a bug. I originally deleted this answer, after the OP posted their answer, but after some testing, I believe that solution is a bug, so I've undeleted this post for anyone who doesn't like the warning1 you get when you use that solution
1. "WARNING: A provider SimpleTest registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider SimpleTest will be ignored."
I'm doing my graduation project, and have run into a dilemma here.
I need to make an application that generates PDFs and emails them to people on a schedule defined by data in the database.
I'm working for a company with this project, and we already have a GlassFish application server that we use. It would be best if the entire solution is delivered in one package, as it is now.
Client with webstart
Web Application etc. is all in one package
My new service needs to run on a separate thread, generate reports and send them out on emails. From what I can read on the web, running your own threads in an application server as GlassFish is highly discouraged, so it sounds like I need to make my own separate application.
Can this really be? What are your comments, and what are the best practices for this?
#Schedule
If you are using Ejb 3.1 (glassfish 3.x), you may use the #Schedule annotation to have the container invoke a method in a specified interval or at a given calendar time. Allowing you to avoid handling threads in your own code
Read about ejb 3.1 timer
#Stateless
public class LabbBean {
#EJB
WorkerEjb workerEjb;
#Schedule(second="*/5", minute="*",hour="*", persistent=false)
public void myMethod() {
for (all jobs found in db){
workerEjb.workerMethod(job);
}
}
}
#Stateless
public class WorkerEjb {
#Asynchronous
public void workerMethod(job) {
//Send emails
}
}
If you wanted to do the work in separate threads, the #Schedule annotated method could call a worker-ejb with the worker-method annotated as #Asynchronous
#Timeout
I just realised you wanted the schedule to be initiated from the database. An option the would be to initiate a bunch of timers programmatically using a #Singleton ejb with #Startup annotation. The timeout annotated method would be called in separate threads if some timers run out at the same time.
#Singleton
#Startup
public class LabbBean {
#Resource
protected TimerService timerService;
#PostConstruct
public void init() {
//Init your timers from the data in the database here
for (all your timers) {
TimerConfig config = new TimerConfig();
config.setInfo("timer1");
config.setPersistent(false);
ScheduleExpression schedule = new ScheduleExpression();
schedule.dayOfMonth(10);
schedule.minute(2);
timerService.createCalendarTimer(schedule, config);
}
}
//method called when timeout occurs
#Timeout
public void timeoutHandler(Timer timer) {
String name = timer.getInfo().toString();
System.out.println("Timer name=" + name);
}
}