I'm new to java.util.concurrent package and i came to a problem with Future object.
This is a conversationScoped bean.
#Inject SomeBean stateFull;
Boolean comp = false, comp1 = false;
public void doSomething(){
stateFull.runProcess();
try {
comp = stateFull.getFuture().get();
System.out.println("Future "+syncEJB.getFuture().get());
updateView();
comp1 = stateFull.getFuture1().get();
System.out.println("Future "+syncEJB.getFuture().get());
updateView();
} catch (InterruptedException ex) {
Logger.getLogger(SynchronizationMB.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(SynchronizationMB.class.getName()).log(Level.SEVERE, null, ex);
}
}
SomeBean looks like this.
#Stateful
public class SomeBean{
#Inject AnotherBean stateLess;
private volatile Future<Boolean> future, future1;
#Asynchronous
public void runProcess(){
future = stateLess.compute();
future1 = stateLess.compute();
}
public Future<Boolean> getFuture() {
return future;
}
public Future<Boolean> getFuture1() {
return future1;
}
}
And AnotherBean:
#Stateless
public class AnotherBean{
#Asynchronous
public Future<Boolean> compute() {
boolean result;
System.out.println("--------------");
System.out.println("completed sync");
System.out.println("--------------");
result = true;
return new AsyncResult<Boolean>(result);
}
}
And now to my problem. I call doSomething() method and i think that according to documentation of Future.get() it should call runProcess() and than wait at
comp = stateFull.getFuture().get();
until future in SomeBean is completed from AnotherBean, but it just keep throwing NullPointerException. Anyone knows why it can be be happening?
-------------------EDIT-----------------------
NullPointer has been corrected. Now i have another problem. Let's say that i set more Future objects in Somebean by calling more methods in runProcess(). And then i want to update my page everytime the Future object get a result to see the progress. How do i do that? Right now i use
private void updateView(){
RequestContext ctx = RequestContext.getCurrentInstance();
ctx.update("mainFrm:info");
}
under every Boolean in doSomething() method, but it doesnt do what i want. All booleans just appear all at once.
NPE happens because starting new thread is a heavy operation, and when you call stateFull.getFuture().get(); new thread is not started yet(so feature is null).
Here the right way of using #Async with Future.
Related
I have a situation where I read data from a YAML file that is important for the application because it is used in several classes. Here is my code:
public class CredentialsReader {
private UserCredentials credentials;
private boolean isReading = false;
public CredentialsReader() {
}
public void readCredentials() {
Runnable readerTask = new Runnable() {
#Override
public void run() {
isReading = true;
parseCredentials();
isReading = false;
System.err.println("Parsed credentials");
}
};
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(readerTask, 0, 60, TimeUnit.SECONDS);
}
private void parseCredentials() {
final File f = new File("/home/dev/IdeaProjects/server/src/main/resources/credentials.yaml");
try {
UserCredentials userCredentials = new ObjectMapper().readValue(f, UserCredentials.class);
this.credentials = userCredentials;
System.out.println(this.credentials.getUsername() + ", " + this.credentials.getPassword());
} catch (IOException e) {
e.printStackTrace();
}
}
public UserCredentials getCredentials() { return this.credentials; }
}
As you see, I read the data every minute and my question is:
Can I delay the return value of getCredentials, so when the method is called I check if isReading is true and then delay the return so I can guarantee that a caller will always get the actual state of the yaml file?
I think there are appropriate locks for similar situations, but this seems like synchronize is sufficient.
synchronized private void parseCredentials() {...}
synchronized public UserCredentials getCredentials() { ... }
By declaring those methods synchronized only one thread at a time will be able to enter the method, essentially a barrier. That means that parseCredentials could have to wait for getCredentials, but getCredentials is so trivially fast you'll never notice.
That will synchronize on an instance of CredentialReader, so if you use more than one, you might want to synchronize on something else. As mentioned it the comments it is better to synchronize on a private object rather than the instance itself. It is a small change:
public class CredentialsReader {
private UserCredentials credentials;
private boolean isReading = false;
final private Object lock = new Object();
...
Then remove the synchronize from the method signature and add a synchronize call in the body.
private void parseCredentials() {
synchronize(lock){
//original code goes here.
}
}
Also, isReading should be volatile.
I do not suggest to do it manually, you could use a CountDownLatch with init value 1 provided in jdk.
You can let the readers calls await, and let the writer calls countDown once data is prepared.
So the reader could always get fully initialized data.
I have a function which is supposed to return a list from the result of a Task API.
#Override
public List performQuery(boolean isPaginationQuery, boolean isSortingQuery {
try {
TaskImpl taskImpl = new TaskImpl(isPaginationQuery,
isSortingQuery);
queryExecutor.submit(taskImpl).get();
return taskImpl.get();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Inner class which performs the updates
private class TaskImpl extends Task<List> {
private boolean isPaginationQuery, isSortingQuery;
public TaskImpl(boolean isPaginationQuery, boolean isSortingQuery) {
this.isPaginationQuery = isPaginationQuery;
this.isSortingQuery = isSortingQuery;
}
#Override
protected List call() throws Exception {
Platform.runLater(() -> {
loaderContainer.setVisible(true);
loaderContainer.toFront();
});
HSession hSession = new HSession();
TaskInfoDao taskInfoDao = new TaskInfoDaoImpl(hSession.getSession(), currentConnection.getConnectionId());
if (!isPaginationQuery && !isSortingQuery) {
paginator.setTotal(taskInfoDao.getTaskInfoWithFiltersCount(paginator.getFilterMap(), false));
}
Stream<TaskInfo> resultStream = taskInfoDao.getTaskInfoWithFilters(paginator.getFilterMap(), false,
paginator.getStartIndex() * paginator.getPageSize(),
paginator.getPageSize() * paginator.getPageGap());
List<TaskInfoTableView> data = createData(resultStream);
hSession.close();
return data;
}
#Override
protected void succeeded() {
super.succeeded();
try {
//set the pagination if the task is complete
//and it is not a pagination query
if (!isPaginationQuery) {
((TaskInfoViewController) uiController).setPagination(
FXCollections.observableArrayList(get()));
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
#Override
protected void cancelled() {
super.cancelled();
updateMessage("Cancelled!");
}
#Override
protected void failed() {
super.failed();
updateMessage("Failed!");
}
}
performQuery function calls the thread and waits for its result.
The loader is being displayed from inside the TaskImpl class using Platform.runLater.
But the loader does not appear until the task has finished i.e. loader appears after the completion of call() function's execution.
When i remove the taskImpl.get() the loader works fine.
Any help is appreciated.
P.S. : Under any case, I need the result of the Task API outside the Inner class( outside TaskImpl )
First of all, it seems like you are not very familiar with asynchronous programming. Having performQuery() to return a List shows that you are expecting to run this synchronously - there is no way for you to return results before you get the results. This is exactly why you are freezing your UI.
The important thing to understand about asynchronous programming is, you would start doing something (i.e. a task) in another thread, and return immediately. When there is result returned from the task, you switch back to the UI (JavaFX Application) thread to update it. You can see this as event-driven approach.
Therefore, for your case, you should directly update the list (the list which you are returning in performQuery()) in the succeeded() method that you have overridden in TaskImpl class.
If the list that you should be updating is not in the scope of TaskImpl, then you can the functional interfaces in java.util.function package to do it for you. This means that you would create that functional interface object at the right scope, and pass in into TaskImpl during object construction, and call that interface in succeeded().
Update
If I assume this is what calls performQuery():
public class MyController {
#FXML
TableView<Foo> tableView;
public void initialize() {
List result = queryController.performQuery(true, true);
tableView.getItems().addAll(result);
}
}
Then, I would probably do something like this:
public class MyController {
#FXML
TableView<Foo> tableView;
public void initialize() {
List result = queryController.performQuery(true, true, list -> tableView.getItems.addAll(list));
}
}
public class QueryController {
#Override
public void performQuery(boolean isPaginationQuery, boolean isSortingQuery, java.util.function.Consumer<List> onQuerySucceeded) {
try {
TaskImpl taskImpl = new TaskImpl(isPaginationQuery,
isSortingQuery, onQuerySucceeded);
queryExecutor.submit(taskImpl);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
private class TaskImpl extends Task<List> {
private final java.util.function.Consumer<List> onQuerySucceeded;
public TaskImpl(boolean isPaginationQuery, boolean isSortingQuery, java.util.function.Consumer<List> onQuerySucceeded) {
this.isPaginationQuery = isPaginationQuery;
this.isSortingQuery = isSortingQuery;
this.onQuerySucceeded = onQuerySucceeded;
}
#Override
protected void succeeded() {
super.succeeded();
// Not sure what the original codes are doing.
try {
//set the pagination if the task is complete
//and it is not a pagination query
if (!isPaginationQuery) {
((TaskInfoViewController) uiController).setPagination(
FXCollections.observableArrayList(get()));
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// This is what is being added in
onQuerySucceeded.accept(this.getValue());
}
}
I have scenario when I need to poll database for specific result. I cant go on within my code until I get the expected result(except the case of passing the timeout interval)
Step A -> Steb B -> Step C
Simple way of doing this(but doesnt feel right for me) was:
numOfRetry=0;
invokeStepA();
while(true)
{
numOfRetry++
boolen result=invokeStepB();
if(result || numOfRetry==3)
{
break;
}
else
{
Thread.sleep(100000)
}
invokeStepC();
Assume the database polling is occurring on Step B.
It doesnt feel right having this while loop on my Spring bean service while calling those jobs.
Maybe I could implement this better?
Thank you.
Farther explanation about my process:
Step A is Invoking external service to do some logic.
Step B need to poll another service which checking if Step A has finished it's work(In case it has finished I can proceed to StepC else I need to try again in X seconds and to check again)
StepC - another logic which must be accomplished only after StepB returned true.
The logic which Step A is doing happens on external service.
In the asynchronous way it happens like
int count = Runtime.getRuntime().availableProcessors();
ExecutorService threadPool = Executors.newFixedThreadPool(count);
invokeStepA();
for (int i = 0; i < RETRY_COUNT; i++) {
Future f = threadPool.submit(new Callable() {
#Override
public Object call() {
return invokeStepB();
}
}
result = (YOUR_DATA_STRUCTURE) f.get();
if (resultIsOK(result)) {
break;
}
}
However, I think since your task is ordered and assuming you cannot go to do something else, using asynchronous isn't really that effective. Please tell me more about your background in case you have special requirements.
EDIT: I think your new requirement looks like you need a proper way to tell if step A is finished fine. So you can use CountDownLatch to check if A has finished properly. I.e.
private final int count = Runtime.getRuntime().availableProcessors();
private final ExecutorService threadPool = Executors.newFixedThreadPool(count);
// invoke step A
invokeStepA();
// submit step B
final CountDownLatch latch = new CountDownLatch(1);
threadPool.submit(new Runnable() {
#Override
public void run() {
invokeStepB();
latch.countDown();
}
});
// wait for step B
boolean result;
try {
result = latch.await(TIME_OUT_IN_MILLISECONDS, TimeUnit.MILLISECOND);
} catch (InterruptedException e) {
}
// Check result
if (result) {
invokeStepC();
} else {
LOG.error("Timeout waiting for step A.");
}
This assumes your invokeStepA() is a blocking method.
Here's another idea by using an event driven approach. This is just out of my mind and not tested ;)
import org.springframework.context.ApplicationEventPublisher;
#Service
public class JobA {
#Autowired
private ApplicationEventPublisher applicationEventPublisher;
#Scheduled(cron = "0 0 * * * ?")
public void doStepA() {
log.debug("some heavy lifting");
Object someData = ....;
applicationEventPublisher.publishEvent(new JobAEvent("Jo, I'm finished", someData));
}
}
#Service
public class JobB implements ApplicationListener<JobAEvent> {
#Autowired
private ApplicationEventPublisher applicationEventPublisher;
#Override
public void onApplicationEvent(final JobAEvent event) {
log.debug("do something more based on the event data");
Object someMoreData = ....;
applicationEventPublisher.publishEvent(new JobBEvent("Dude, me too", event.getSomeData(), someMoreData));
}
}
#Service
public class JobC implements ApplicationListener<JobBEvent> {
#Autowired
private ApplicationEventPublisher applicationEventPublisher;
#Override
public void onApplicationEvent(final JobBEvent event) {
log.debug("do even more work");
}
}
EDIT:
You can also call the method directly but then it runs synchronosly. Another possibilty is using '#Async'
My Entitymanager has no transaction when persisting an object in #PostConstruct.
I have no clue why and how to fix this, can anyone help me?
PS. If you need any other data, please ask
TestmachineManager
#Singleton
public class TestmachineManager {
#PersistenceContext
private EntityManager em;
private TimerTask handler = new TimerTask() {
#Override
public void run() {
DayPlanning planning = getPlanning();
Order order = planning.getNextInLine();
if(order instanceof Order) {
em.merge(planning);
List<String> tests = new ArrayList();
for(Test test : order.getTests()) {
tests.add(test.getName());
}
TestmachineSender.orderTests(order.getId(), order.getDomain(), tests);
timer.schedule(checker, safetycheckAt());
}
else {
timer.schedule(handler, postponeTo());
}
}
};
#PostConstruct
public void init() {
if(getPlanning().hasActiveTest()) {
handler.run();
}
}
private DayPlanning getPlanning() {
LocalDate today = new LocalDate(
Calendar.getInstance().getTime());
try {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<DayPlanning> query = cb.createQuery(DayPlanning.class);
Root dayPlanning = query.from(DayPlanning.class);
Predicate predicateDate = cb.equal(dayPlanning.get("dateOfPlanning"), today.toDate());
query.select(dayPlanning).where(predicateDate);
return em.createQuery(query).getSingleResult();
} catch(NoResultException ex) {
DayPlanning newPlanning = new DayPlanning(today);
em.persist(newPlanning);
return newPlanning;
}
}
}
Stacktrace
Caused by: javax.persistence.TransactionRequiredException
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:163)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:145)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:263)
at TestmachineManager.getPlanning(TestmachineManager.java:130)
at TestmachineManager.init(TestmachineManager.java:78)
You have a transaction in #PostConstruct for the Singleton bean. The moment you are loosing your transaction is when you launch a new timer using timer.schedule(checker, safetycheckAt()); or timer.schedule(handler, postponeTo());. I think that the timer object that you are using is actually java.util.Timer, looking at the signature.
You should try using the EJB TimerService resource. For example:
#Resource
private TimerService timerService;
#Timeout
public void run() {
DayPlanning planning = getPlanning();
Order order = planning.getNextInLine();
if(order instanceof Order) {
em.merge(planning);
List<String> tests = new ArrayList();
for(Test test : order.getTests()) {
tests.add(test.getName());
}
TestmachineSender.orderTests(order.getId(), order.getDomain(), tests);
// if the checker handler doesn't need to run transactionally you could leave it like it was before
timer.schedule(checker, safetycheckAt());
// otherwise you could create a checker EJB that uses #Timeout in the same manner or #Scheduled from EJB3.1
} else {
// postpone timer
timerService.createTimer(postponeTo(), "postponed timer information");
}
}
#PostConstruct
public void init() {
if(getPlanning().hasActiveTest()) {
timerService.createTimer(computeDelay(), "timer information");
// or you could use the other create methods of the timerService, those that fits your needs better
}
}
I didn't tested the code, it's just rough code. Hope it helps.
The run method of Runnable has return type void and cannot return a value. I wonder however if there is any workaround of this.
I have a method like this:
public class Endpoint {
public method() {
Runnable runcls = new RunnableClass();
runcls.run()
}
}
The method run is like this:
public class RunnableClass implements Runnable {
public JaxbResponse response;
public void run() {
int id = inputProxy.input(chain);
response = outputProxy.input();
}
}
I want to have access to response variable in method. Is this possible?
Use Callable<V> instead of using Runnable interface.
Example:
public static void main(String args[]) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(3);
Set<Future<Integer>> set = new HashSet<>();
for (String word : args) {
Callable<Integer> callable = new WordLengthCallable(word);
Future<Integer> future = pool.submit(callable);
set.add(future);
}
int sum = 0;
for (Future<Integer> future : set) {
sum += future.get();
}
System.out.printf("The sum of lengths is %s%n", sum);
System.exit(sum);
}
In this example, you will also need to implement the class WordLengthCallable, which implements the Callable interface.
public void check() {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> result = executor.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return 10;
}
});
try {
int returnValue = result.get();
} catch (Exception exception) {
//handle exception
}
}
Have a look at the Callable class. This is usually submited via an executor service
It can return a future object which is returned when the thread completes
Yes, there are workaround. Just use queue and put into it value which you want to return. And take this value from another thread.
public class RunnableClass implements Runnable{
private final BlockingQueue<jaxbResponse> queue;
public RunnableClass(BlockingQueue<jaxbResponse> queue) {
this.queue = queue;
}
public void run() {
int id;
id =inputProxy.input(chain);
queue.put(outputProxy.input());
}
}
public class Endpoint{
public method_(){
BlockingQueue<jaxbResponse> queue = new LinkedBlockingQueue<>();
RunnableClass runcls = new RunnableClass(queue);
runcls.run()
jaxbResponse response = queue.take(); // waits until takes value from queue
}
}
If you add a field to RunnableClass you can set it in run and read it in method_. However, Runnable is a poor (the Java keyword) interface as it tells you nothing about the (the concept) interface (only useful line of the API docs: "The general contract of the method run is that it may take any action whatsoever."). Much better to use a more meaningful interface (that may return something).
One way is, we have to use Future - Callable approach.
Another way is, Instead of returning value, you can hold in object
Example:
class MainThread {
public void startMyThread() {
Object requiredObject = new Object(); //Map/List/OwnClass
Thread myThread = new Thread(new RunnableObject(requiredObject)).start();
myThread.join();
System.out.println(requiredObject.getRequiredValue());
}
}
class RunnableObject implements Runnable {
private Object requiredObject;
public RunnableObject(Object requiredObject) {
this.requiredObject = requiredObject;
}
public void run() {
requiredObject.setRequiredValue(xxxxx);
}
}
Because object scope is in the same scope so that you can pass object to thread and can retrieve in the main scope. But, most important thing is, we have to use join() method. Because main scope should be waiting for thread completion of its task.
For multiple thread case, you can use List/Map to hold the values from threads.
Try the following
public abstract class ReturnRunnable<T> implements Runnable {
public abstract T runForResult();
#Override
public void run() {
runForResult();
}
}
Take a look at the callable interface, perhaps this suites your needs. You can also try to get the value of the response field by calling a setter-method inside of your run() method
public void run() {
int id;
id =inputProxy.input(chain);
response = outputProxy.input();
OuterClass.setResponseData(response);
}