I am trying to use ListenableFutues for the first time, getting an error while using addCallback method, Please help.
Attached is the snapshot of the code.
Error is:
error: <identifier> expected
Futures.addCallback(futureRequest,new FutureCallback<T>() {
^
error: <identifier> expected
Futures.addCallback(futureRequest,new FutureCallback<T>() {
^
You can implement ListenableFuture Callback like below.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
public class EventDriver<T> {
private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
public void prepare() {
Callable<T> task = null; // Whatever task you need to assign
ExecutorService executorService = Executors.newFixedThreadPool(10);
ListeningExecutorService service = MoreExecutors.listeningDecorator(executorService);
ListenableFuture<T> futureRequest = service.submit(task);
Futures.addCallback(futureRequest, new FutureCallback<T>() {
#Override
public void onSuccess(T result) {
logger.info("Sucess..");
}
#Override
public void onFailure(Throwable t) {
logger.info("Failure..");
}
});
}
}
Related
I have encountered an interesting yet a terrifying situation. My application has two features namely, OtpListener and CdmMonitor running on two separate threads. For now, only the OtpListener feature was required so I commented out CdmMonitor in the main class.
However, I still see the logs for the commented out class CdmMonitorService. This service was running (when it shouldn't as it was commented)
Do threads implemented from the Runnable class operate this way? I did not find anything of the sort in its documentation.
Main Class: OtpTrackerApp.java
package dev.xfoil.otpTracker;
import dev.xfoil.otpTracker.service.CdmMonitorService;
import dev.xfoil.otpTracker.service.OTPListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan({"dev.xfoil.otpTracker.*","dev.xfoil.shared.*", "dev.xfoil.shared.dal.repositories.springdata.*", "dev.xfoil.shared.dal.entities.*","dev.xfoil.shared.dal.cache.*"})
public class OtpTrackerApp implements CommandLineRunner {
#Autowired
public OTPListener otpListener;
// #Autowired
// public CdmMonitorService cdmMonitorService;
public static void main(String[] args){
SpringApplication.run(OtpTrackerApp.class, args);
}
#Override
public void run(String... args) throws Exception {
// Thread monitoringThread = new Thread(cdmMonitorService);
// monitoringThread.start();
otpListener.startListening();
}
}
CdmMonitorService.java
package dev.xfoil.otpTracker.service;
import com.google.common.flogger.FluentLogger;
import dev.xfoil.otpTracker.firebase.FirestoreManager;
import dev.xfoil.shared.dal.repositories.springdata.MachineMonitorRepo;
import dev.xfoil.shared.dal.repositories.springdata.MachineOperationsHistoryRepo;
import dev.xfoil.shared.dal.repositories.springdata.MachinesRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
#Service
public class CdmMonitorService implements Runnable {
FluentLogger logger = FluentLogger.forEnclosingClass();
#Autowired
MachineMonitorRepo machineMonitorRepo;
#Autowired
MachineOperationsHistoryRepo machineOperationsHistoryRepo;
#Autowired
MachinesRepo machinesRepo;
#Autowired
FirestoreManager firestoreManager;
public CdmMonitorService() {
}
#Override
#Scheduled(fixedDelay = 120000l)
public void run() {
try {
// code removed for brevity
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
logger.atWarning().log("Exception in CDM Monitor Thread " + e);
}
}
}
OtpListener.java
package dev.xfoil.otpTracker.service;
import com.google.common.flogger.FluentLogger;
import dev.xfoil.shared.dal.entities.AccountLedger;
import dev.xfoil.shared.dal.models.OTP;
import dev.xfoil.shared.dal.repositories.springdata.LedgerRepo;
import dev.xfoil.shared.dal.repositories.springdata.NoteCountRepo;
import dev.xfoil.shared.dal.repositories.springdata.UtilRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
#Service
public class OTPListener {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
#Autowired
UtilRepo utilRepo;
#Autowired
ThirdPartyApiCalls discordServer;
#Autowired
NoteCountRepo noteCountRepo;
private static LocalDateTime latestOTPTime;
#Value("#{${webhooks}}")
HashMap<String, String> discordLink = new HashMap<String, String>();
#PostConstruct
public LocalDateTime getLatestOTPTimestamp() {
latestOTPTime = utilRepo.getTimeOfLatestOTP();
return latestOTPTime;
}
public void startListening() throws InterruptedException {
logger.atInfo().log("Current in-mem links:");
try {
// code commented for brevity
Thread.sleep(5 * 60 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class ServiceLoaderDemo {
public CPService demo() {
ServiceLoader<CPService> serviceLoader = ServiceLoader.load(CPService.class);
return iterate(serviceLoader);
}
public CPService iterate(ServiceLoader<CPService> serviceLoader) {
CPService nonDefault = null;
for (CPService cpService : serviceLoader) {
cpService.show();
if(!cpService.isDefault())
{
nonDefault = cpService;
}
}
return nonDefault;
}
}
I need to write unit tests for iterate method with following cases:
a default service and a non-default service
a default service only
a non-default service only
more than one non-default service
I tried to mock ServiceLoader class as follows:
import static org.fest.reflect.core.Reflection.method;
import static org.powermock.api.mockito.PowerMockito.mock;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import junit.framework.TestCase;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ServiceLoader.class)
public class ServiceLoaderDemoTest extends TestCase {
private ServiceLoaderDemo serviceLoaderDemo = new ServiceLoaderDemo();
public void testIterate() {
final ServiceLoader mockServiceLoader = mock(ServiceLoader.class);
IteratorDummy iterator = new IteratorDummy();
iterator.cpServices.add(new CPServiceImplTwo());
iterator.cpServices.add(new CPServiceImplOne());
PowerMockito.when(mockServiceLoader.iterator()).thenReturn(iterator);
CPService methodToTest = null;
try {
methodToTest = method("iterate").withReturnType(CPService.class).withParameterTypes(ServiceLoader.class).in(serviceLoaderDemo).invoke(mockServiceLoader);
} catch (SecurityException e) {
e.printStackTrace();
}
assertEquals(methodToTest.getClass(), ServiceLoaderDemoTest.class);
}
}
class IteratorDummy implements Iterator<CPService> {
public List<CPService> cpServices = new ArrayList<>();
#Override
public boolean hasNext() {
return cpServices.iterator().hasNext();
}
#Override
public CPService next() {
CPService service = cpServices.iterator().next();
return service;
}
}
This is throwing NullPointerException. I am unable to write unit tests for this. please help me.
I have a Spring-Boot application which is going to be an orchestration service for several other processes we want to trigger. I have it currently set up using Spring Scheduling pulling crons dynamically from a database. I threw in a rest method to trigger the process to pull new cron information from the database. This logic all works correctly. The only "issue" is that it doesn't use the new cron information until the next scheduled run which gets to the real question. Is there a way to interrupt the current Trigger and schedule one again using the updated cron information. Here is the application for reference:
package com.bts.poc;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
#SpringBootApplication
#EnableScheduling
#RestController
#RequestMapping("/APSCommon/Scheduling")
public class Application implements SchedulingConfigurer {
#Autowired
private DynamicCron dynamicCron;
#Autowired
PropertyManager propertyManager;
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class);
}
private String cronConfig() {
String cronTabExpression = propertyManager.getProperty("COMPANY", "JOB_NAME","CRON_EXPRESSION");
return cronTabExpression;
}
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(new Runnable() {
#Override
public void run() {
dynamicCron.runJob();
}
}, new Trigger() {
#Override
public Date nextExecutionTime(TriggerContext triggerContext) {
String cron = cronConfig();
CronTrigger trigger = new CronTrigger(cron);
Date nextExec = trigger.nextExecutionTime(triggerContext);
DynamicCron.cronExpression = cron;
return nextExec;
}
});
}
#RequestMapping(value = "/reloadScheduling", method = RequestMethod.GET)
public String reloadScheduling() {
PropertyManager.setResetProperties(true);
return "schedules will be altered next run";
}
}
So using SchedulingConfigurer->configureTasks you can't get access to the ScheduledFuture(s) in the Spring version I am using (4.2.7.RELEASE). From several posts I have read it has been mentioned as possible functionality for the future. I got around this by doing the following:
package com.bts.poc;
import com.bts.poc.service.DynamicCron;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.ScheduledFuture;
#SpringBootApplication(exclude = MessageSourceAutoConfiguration.class)
#EnableScheduling
#RestController
public class Application extends SpringBootServletInitializer {
#Autowired
private DynamicCron dynamicCron;
#Autowired
private PropertyManager propertyManager;
private static List<ScheduledFuture> scheduledFutures = new ArrayList<>();
private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
private static TaskScheduler scheduler;
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
private String cronConfig() {
return propertyManager.getProperty("COMPANY", "JOB_NAME", "CRON_EXPRESSION");
}
#RequestMapping(value = {"scheduling/start"}, method = RequestMethod.GET)
public #ResponseBody String startScheduling() {
scheduleAll();
LOGGER.info("Scheduling of jobs has been started.");
return "Scheduling of jobs has been started.";
}
#RequestMapping(value = {"scheduling/cancel"}, method = RequestMethod.GET)
public #ResponseBody String cancelScheduling() {
cancelAll();
LOGGER.info("Cancelling all scheduled jobs.");
return "Cancelling all scheduled jobs.";
}
private void scheduleAll() {
LOGGER.info("Scheduling all applications to run.");
cancelAll();
//eventually go through the database and load all jobs to be scheduled here.
schedule(cronConfig());
}
/**
* Cancel all the scheduled reports
*/
private void cancelAll() {
for (ScheduledFuture scheduledFuture : scheduledFutures) {
scheduledFuture.cancel(true);
}
scheduledFutures.clear();
}
/**
* Schedule the scheduled report with the given cron schedule information
*/
private void schedule(String cronSchedule) {
TimeZone tz = TimeZone.getDefault();
LOGGER.info("Setting up application {} to execute with cron string: '{}'.", cronSchedule);
CronTrigger trigger = new CronTrigger(cronSchedule, tz);
scheduler = scheduler();
if (scheduler == null) {
LOGGER.error("Unable to schedule job as scheduler was not found");
return;
}
ScheduledFuture<?> future = scheduler.schedule(new DynamicCron(), trigger);
scheduledFutures.add(future);
}
#Bean
public TaskScheduler scheduler() {
if (scheduler == null) {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
scheduler.afterPropertiesSet();
}
return scheduler;
}
}
This basically replicates the functionality the ScheduledTaskRegistrar provides allowing you manage the ScheduledFuture(s). Hopefully this can help someone else in the future.
I am trying to create a job in java play2 using akka.
I always get the same error error: cannot find symbol
And it points to system.actorOf() Intellij and Eclipse don't give me an error msg.
But I can not find this method. I used the following imports
import play.libs.Akka;
import akka.actor.ActorSystem;
import akka.actor.ActorRef;
import akka.actor.UntypedActorFactory;
import akka.actor.UntypedActor;
import akka.actor.Props;
import akka.actor.ActorRefFactory;
Maybe the docs are outdated and they have removed the system.actorOf() ?
public class Global extends GlobalSettings {
ActorRef tickActor = system.actorOf(new Props().withCreator(new UntypedActorFactory() {
public UntypedActor create() {
return new UntypedActor() {
public void onReceive(Object message) {
if (message.equals("Log")) {
controllers.Application.log();
} else {
unhandled(message);
}
}
};
}
}));
#Override
public void onStart(Application app) {
Cancellable cancellable = system.scheduler().schedule(Duration.Zero(), Duration.create(10, TimeUnit.SECONDS),
tickActor, "Log");
}
}
EDIT:
.
oh... google redirected me to the outdated documentation. It's Akka.System() now..
Can anyone give me an example on how to create the tickActor with up2date code?
http://www.playframework.org/documentation/2.0.2/JavaAkka
I strongly suggest that you take a look at the Akka documentation about actors and schedulers.
You can also take a look at this question: Play Framework 2.0 schedules an Akka Actor at server launch
solved it.
Btw there are some typos in the documentation.
import java.util.concurrent.TimeUnit;
import play.*;
import play.mvc.*;
import play.mvc.Http.RequestHeader;
import static play.mvc.Results.*;
import play.libs.Akka;
import akka.actor.ActorSystem;
import akka.actor.ActorRef;
import akka.actor.UntypedActorFactory;
import akka.actor.UntypedActor;
import akka.actor.Props;
import akka.actor.ActorRefFactory;
import akka.util.*;
public class Global extends GlobalSettings {
ActorRef tickActor;
#Override
public void onStart(Application app) {
Logger.info("D");
tickActor = Akka.system().actorOf((new Props().withCreator(new UntypedActorFactory() {
public UntypedActor create() {
return new UntypedActor() {
public void onReceive(Object message) {
if (message.equals("Log")) {
//Do something
// controllers.Application.log();
} else {
unhandled(message);
}
}
};
}
})));
Akka.system().scheduler().schedule(
Duration.create(0, TimeUnit.MILLISECONDS),
Duration.create(30, TimeUnit.MINUTES),
tickActor,
"Log"
);
}
}
I have mocked a method called methodA().
I have a linked list called linkedListA.
Now,
i have a line of code to mock the return of methodA, as such
when(methodA()).thenReturn(linkedListA.get(0)).thenReturn(linkedListA.get(1)).thenReturn(linkedListA.get(2)) and so on
Now, is there a more efficient/cleaner way to write all the thenReturns, for instance, like in a loop? So, that I do not have to write tons of thenReturns
Thanks
I think the first improvement would be to use this:
when(methodA()).thenReturn(linkedListA.get(0), linkedListA.get(1), linkedListA.get(2)) and so on
Moreover, you could you the thenAnswer method to return a value:
final AtomicInteger i = new AtomicInteger(0);
when(methodA()).thenAnswer(new Answer<YourType>() {
#Override
public YourType answer(InvocationOnMock invocation) {
return linkedListA.get(i.getAndIncrement());
}
});
Example:
import static org.powermock.api.mockito.PowerMockito.when;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(Blub.class)
public class Mockexample {
#Test
public void test() {
Blub blub = PowerMockito.mock(Blub.class);
final List<Integer> counter = Arrays.asList(1, 2, 3);
final AtomicInteger i = new AtomicInteger(0);
// blub.size() is final, only reason to use PowerMockito here
when(blub.size()).thenAnswer(new Answer<Integer>() {
#Override
public Integer answer(InvocationOnMock invocation) throws Throwable {
return counter.get(i.getAndIncrement());
}
});
System.out.println(blub.size());
System.out.println(blub.size());
System.out.println(blub.size());
}
}
The Blub clas:
public class Blub {
public final int size() {
return 0;
}
}