static method throws NullPointerException when I try to access it inside thread - java

Here I've got a thread
#Component("sessionStateListenerThread")
public class SessionStateListenerThread extends Thread {
private static final String DEFAULT_RESULT = "expired";
private List<DeferredResult<String>> subscribed = Collections
.synchronizedList(new ArrayList<DeferredResult<String>>());
/**
* Main thread loop for checking session state.
*/
#Override
public void run() {
while (true) {
synchronized (subscribed) {
try {
if (null == SecurityHelper.getUserLogin()) {
Iterator<DeferredResult<String>> it = subscribed.iterator();
while (it.hasNext()) {
DeferredResult<String> result = it.next();
result.setResult(DEFAULT_RESULT);
it.remove();
}
}
} catch (NullPointerException e) {
}
}
}
}
/**
* Adds client to listen session state.
*
* #param client
*/
public void addClient(DeferredResult<String> client) {
synchronized (subscribed) {
subscribed.add(client);
}
};
}
This class is used to wrap that thread
#Component
#DependsOn("sessionStateListenerThread")
public class SessionStateListener {
#Autowired
private SessionStateListenerThread thread;
#PostConstruct
public void configThread() {
thread.setDaemon(true);
thread.setName("SessionStateChecker");
}
/**
* Starts listener.
*/
public void startListener() {
thread.start();
}
/**
* Adds client to write result.
*
* #param client object to write result
*/
public void addSessionStateListener(DeferredResult<String> client) {
thread.addClient(client);
}
}
I put method startListener inside controller method. Also in controller I access method getUserLogin.
String login = SecurityHelper.getUserLogin(); // successfully access it
listener.startListener();
Method run in thread want to access this method getUserLogin too.
But despite login value being not null - invokation of SecurityHelper.getUserLogin() throws NullPointerException inside thread.
What's the problem? getUserLogin looks like this
return SecurityContextHolder.getContext().getAuthentication().getName();
Stacktrace is somehow small (e.printstacktrace())
java.lang.NullPointerException
at com.ui.web.security.SecurityHelper.getUserLogin(SecurityHelper.java:45)
at com.ui.web.controller.rest.poll.SessionStateListenerThread.run(SessionState
ListenerThread.java:41)

It's because you can't get current session data (context) into separate thread than current request thread.
You will be able to get any session data into any controller method, because any controller method will be executed within request thread.

Related

Spring Boot - How to achieve this execution?

I have a couple controller methods that must not be allowed to run at the same time:
#Scheduled(cron = "0 * * * * *")
public void first() {
// Acts on database
}
#RequestMapping(value = "/second", method = RequestMethod.POST)
public void second() {
// Also acts on same database
}
First one runs only as a scheduled job. Second one only runs as an HTTP request.
When second() gets called I want it to wait until first() finishes if it is running, then run immediately afterwards. If first() is not running, want second() to run and block first() from running while second() is still running. By block I mean don't allow first() to run at all, don't wait for second() to finish or queue it to run later either. It will attempt to run again only on its next scheduled run.
Edit:
If second() gets requested again while the previous request to second() has not yet completed, want that new request to be ignored.
If you have to maintain this only on one instance of your application, then you can use for example AtomicBoolean:
Let's create additional method, where you make something like this:
private AtomicBoolean isSecondRunning = new AtomicBoolean();
#Scheduled(cron = "0 * * * * *")
public void first() {
if (isSecondRunning.get()) {
return; // 1
}
execute();
}
#RequestMapping(value = "/second", method = RequestMethod.POST)
public void second() {
isSecondRunning.set(true); // 2
try {
execute();
} finally {
isRunning.set(false); // 3
}
}
public synchronized void execute(){
// here execute the code
}
Code explanation:
if isSecondRunning is true, then return from first without execution, if is false, then skip if and go to execute() method
when second is executed, then set isSecondRunning to true and then execute
set isSecondRunning to false, and do it inside finally block, so we can be sure, that it is set to false even if some exception occurs in your execution
The execute method is synchronized, so if first is running, then second will wait
The easiest way would to make both call a method in another layer (e.g. a service). That method, if declared on a singleton bean, can be synchronized so only one thread will be able to execute it at the same time in the same server.
class ScheduledTasks{
#Autowired private Service service;
#Scheduled(cron = "0 * * * * *")
public void first() {
service.doStuff();
}
}
class MyController{
#Autowired private Service service;
#RequestMapping(value = "/second", method = RequestMethod.POST)
public void second() {
service.doStuff();
}
}
#Service
class Service{
public synchronized void doStuff(){...}
}
Be aware, though, that it will cause concurrent requests to your endpoint to seemingly "halt" until the previous ones have completed, when they attempt to call that method.
As an alternative, you may want to convert your Scheduled method to a Quartz job and modify the trigger when your controller is called. This would also require some degree of synchronization so the triggers are modified atomically among concurrent requests, and also you may still need a synchronized method to guarantee that if first() is already running you don't execute the changes from second().
The problem is you can't really do anything simple because the outcome of whether a job is allowed to be queued or not depends on what jobs are already in the queue.
I would suggest you need a JobManager that controls the queue, and a JobRunner that takes any jobs from the queue and runs them. You need to both check the contents of the queue and add to the queue under the same exclusive lock.
public class JobManager {
private final Queue<Jobs> queue;
private final JobRunner jobRunner;
public JobManager() {
this.queue = new LinkedList<Jobs>();
this.jobRunner = new JobRunner(this);
jobRunner.start();
}
public synchronized void requestFirst() {
if (queue.isEmpty()) {
queue.add(Jobs.FIRST);
notifyAll();
}
}
public synchronized void requestSecond() {
if (!queue.contains(Jobs.SECOND)) {
queue.add(Jobs.SECOND);
notifyAll();
}
}
public synchronized Jobs getJob() throws InterruptedException {
while (queue.isEmpty()) {
wait();
}
return queue.peek();
}
public synchronized void notifyFinished(Jobs job) {
queue.remove(job);
}
public void startRunner() {
jobRunner.start();
}
public void stopRunner() {
jobRunner.stopRunner();
}
}
public class JobRunner extends Thread {
private final JobManager jobManager;
private volatile boolean stopping;
public JobRunner(JobManager jobManager) {
this.jobManager = jobManager;
this.stopping = false;
}
public void stopRunner() {
stopping = true;
this.interrupt();
}
#Override
public void run() {
while (!stopping) {
try {
Jobs job = jobManager.getJob();
if (job.equals(Jobs.FIRST)) {
// run first job
} else if (job.equals(Jobs.SECOND)) {
// run second job
}
jobManager.notifyFinished(job);
} catch (InterruptedException ignored) {}
}
}
}
public enum Jobs {
FIRST,
SECOND
}
#Controller
public class WebAccess {
private final JobManager jobManager;
public WebAccess() {
jobManager = new JobManager();
}
#Scheduled(cron = "0 * * * * *")
public void first() {
jobManager.requestFirst();
}
#RequestMapping(value = "/second", method = RequestMethod.POST)
public void second() {
jobManager.requestSecond();
}
#EventListener(ContextClosedEvent.class)
public void stopRunner() {
jobManager.stopRunner();
}
}
Unfortunately because of your complicated requirements for choosing first or second job, you need to hold a synchronization lock whilst checking the queue and deciding whether to add the job or not.
This kind of approach may be extremely difficult to test so probably it should be a last resort.
If you want to get Spring to do the autowiring you could annotate it accordingly.

Null Pointer Exception when Data-Binding a value from a Service in JavaFX

I am trying to get a simple data-binding example to work to better understand using the JavaFX service class and possibly incorporating it into a project I am working on, however I have been unable to bind the value that shoudl be returned from the service (an Integer) to an integer in the class that calls the service.
I have checked the debugger and confirmed that the task is actually returning the value but I keep getting a null pointer exception stating that I "Cannot bind to null" for the line of code that does the binding, however, the other properties that I have binded seem to be working fine
Main Class
public class Main extends Application {
private Service<ObservableValue<Integer>> service;
#Override
public void start(Stage primaryStage){
/**********************************
* Start of Multi-Threading Logic
**********************************/
service = new EmployeeService();
ObjectProperty<Integer> size = new SimpleObjectProperty<>(0);
size.bind(service.getValue()); // Null Pointer Exception Cause
progressBar.progressProperty().bind(service.progressProperty());
progressBar.visibleProperty().bind(service.runningProperty());
progressLabel.textProperty().bind(service.messageProperty());
progressLabel.setVisible(false);
/*************************************************************
* Start Task Button Event Handler
*
* If the service state is succeeded or cancelled
* then the service must first be reset before starting
*
* if the service state is ready then start the service
*
* if the service state is something other than the above
* like running or failed, then do nothing
*************************************************************/
startTaskButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if(service.getState() == Service.State.SUCCEEDED
|| service.getState() == Service.State.CANCELLED) {
service.reset();
service.start();
}else if(service.getState() == Service.State.READY) {
service.start();
}else {
System.out.println("Not doing anything");
}
}
});
/*************************************************************
* Cancel Task Button Event Handler
*
* The service should only be canceled if it is currently
* running, else do nothing.
*************************************************************/
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if(service.getState() == Service.State.RUNNING) {
service.cancel();
}
}
});
Service Impl Class
/*************************************************************
* Custom Service Impl class that creates the DisplayDataTask
*************************************************************/
class EmployeeService extends Service<ObservableValue<Integer>>{
#Override
protected Task<ObservableValue<Integer>> createTask() {
return new DisplayDataTask();
}
}
Task Impl Class
/*************************************************************
* Custom Task Impl class that creates a basic list
* and returns the length of the list in the call method
*************************************************************/
class DisplayDataTask extends Task<ObservableValue<Integer>> {
#Override
protected ObservableValue<Integer> call() throws Exception {
int randomNum = 71890;
Thread.sleep(5000); // Sleep for 5 seconds to simulate a task
ObjectProperty<Integer> size = new SimpleIntegerProperty(randomNum).asObject();
return size;
}
#Override
protected void cancelled() {
super.cancelled();
updateMessage("Operation Cancelled");
System.out.println("The " + this.getClass().getSimpleName() + " has been canceled.");
}
}
Service.getValue() returns the service's current value, and before the service completes, it returns null.
You almost certainly don't want the service to return an ObservableValue<Integer> here, you want it to return an actual Integer. So rewrite the service as:
class EmployeeService extends Service<Integer>{
#Override
protected Task<Integer> createTask() {
return new DisplayDataTask();
}
}
with
class DisplayDataTask extends Task<Integer> {
#Override
protected Integer call() throws Exception {
int randomNum = 71890;
Thread.sleep(5000); // Sleep for 5 seconds to simulate a task
Integer size = randomNum ;
return size;
}
#Override
protected void cancelled() {
super.cancelled();
updateMessage("Operation Cancelled");
System.out.println("The " + this.getClass().getSimpleName() + " has been canceled.");
}
}
and then you can just do
size.bind(service.valueProperty());

How to use LinkedBlockingQueue to run tasks

I am currently trying to get my code to print what is in the method of simpleTask 20 times using the code in simpleTesting. The idea is that simpleTesting adds 20 instances of simpleTask to a queue then they are taken from the queue in simplePoolThread. What should happen is that it prints out the testing message 20 times then continues to run while looking for more things from the queue (but there are none). Instead it is currently just not printing anything and continuously running. Here is my code (a lot of it is interfaces, I believe the problem lies in the simpleThreadPool code):
package simpleThreadPool;
/**
* <<-- Pool Thread -->>
*
* It will be running continuously. It will try to retrieve new tasks when it is idle.
*/
public interface ISimplePoolThread extends Runnable {
/**
* Use an infinite loop to retrieve and perform tasks.
*/
#Override
public void run();
}
.
package simpleThreadPool;
/**
* <<-- Simple Task -->>
*
* ISimpleTask is to be performed by PoolThread.
*/
public interface ISimpleTask{
/**
* #1. Create a class to implement ISimpleTask, put content of the task to method run().
*/
public void run();
}
.
package simpleThreadPool;
/**
* <<-- Thread Pool -->>
* It manages a queue of tasks, starts some pool threads.
*
* #1. Create a task queue by using queue data structures, or designing your own data structure.
*/
public interface ISimpleThreadPool {
/**
* #1. Initialize your queue (or do so in somewhere)
* #2. Starts some ISimplePoolThreads.
*/
public void start();
/**
* #1. Stops everything
*/
public void stop();
/**
* #1. Add a task to your queue.
*/
public void addTask(ISimpleTask task);
}
.
package simpleThreadPool;
public class SimpleTask implements ISimpleTask {
#Override
public void run() {
System.out.println("testing testing 1 2 3");
}
}
.
I think the problem lies in this piece of code, where the tasks are taken from the queue:
package simpleThreadPool;
import java.util.concurrent.LinkedBlockingQueue;
public class SimplePoolThread implements ISimplePoolThread, Runnable {
private LinkedBlockingQueue<ISimpleTask> queue = new LinkedBlockingQueue<>();
#Override
public void run() {
while(true) {
System.out.println("Inserting Element: ");
try {
queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
.
package simpleThreadPool;
import java.util.concurrent.LinkedBlockingQueue;
public class SimpleThreadPool implements ISimpleThreadPool {
private LinkedBlockingQueue<ISimpleTask> queue = new LinkedBlockingQueue<>();
#Override
public void start() {
(new Thread(new SimplePoolThread())).start();
}
#Override
public void stop() {
try {
queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void addTask(ISimpleTask task) {
try {
queue.put(task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
.
the testing file:
package simpleThreadPool;
public class SimpleTesting implements ISimpleTask{
private int i;
public SimpleTesting(int i){
this.i = i;
}
#Override
public void run() {
System.out.println(i);
}
public static void main(String args[]){
// Initialize thread pool
SimpleThreadPool pool = new SimpleThreadPool();
pool.start();
// Create 20 tasks
for(int i = 1; i<=20; i++){
pool.addTask(new SimpleTesting(i));
}
}
}
The task queue in your SimplePoolThread is a blocking queue. As soon as it starts it executes queue.take(). Take is a blocking operation. The thread sits there waiting forever until something else adds a task into the queue.
Your hunch on the problem location was pretty close. The issue is that the queue in SimplePoolThread and the queue in SimpleThreadPool are not the same; you have two separate queues. So when SimpleTesting adds tasks they go into Pool's queue and NOT into the Thread's queue. So the thread will sit there forever waiting on nothing. You also forgot to actually run your tasks inside of SimplePoolThread.
Try the following instead.
public class SimpleThreadPool implements ISimpleThreadPool {
private LinkedBlockingQueue<ISimpleTask> queue = new LinkedBlockingQueue<>();
#Override
public void start() {
(new Thread(new SimplePoolThread(queue))).start();
}
Note that the queue from the pool was passed into the thread. The thread then keeps a reference to this queue. During the thread's run() it now also actually runs the task.
public class SimplePoolThread implements ISimplePoolThread, Runnable {
private LinkedBlockingQueue<ISimpleTask> queue;
public SimplePoolThread(LinkedBlockingQueue<ISimpleTask> queue)
{
this.queue = queue;
}
#Override
public void run() {
while(true) {
System.out.println("Inserting Element: ");
try {
ISimpleTask task = queue.take();
task.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Here's the output:
Inserting Element:
1
Inserting Element:
2
Inserting Element:
3
..etc..
I assume this is for homework otherwise I would tell you not to reinvent the wheel and go use Java's built-in pooling services.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html

Generic array creation for java.lang.Thread

Intellij IDEA is complaining about Generic array creation
public abstract class BaseImageLoader<CacheItem>
{
private ImageLoaderThread[] workerThreads;
public BaseImageLoader(Context context)
{
...
workerThreads = new ImageLoaderThread[DEFAULT_CACHE_THREAD_POOL_SIZE];//Generic array creation error
...
}
}
ImageLoaderThread is in fact a subclass of java.lang.Thread, its not generic
I dont get what im doing wrong
this works fine:
Thread[] threads = new Thread[DEFAULT_CACHE_THREAD_POOL_SIZE];
ImageLoaderThread class
private class ImageLoaderThread extends Thread
{
/**
* The queue of requests to service.
*/
private final BlockingQueue<ImageData> mQueue;
/**
* Used for telling us to die.
*/
private volatile boolean mQuit = false;
/**
* Creates a new cache thread. You must call {#link #start()}
* in order to begin processing.
*
* #param queue Queue of incoming requests for triage
*/
public ImageLoaderThread(BlockingQueue<ImageData> queue)
{
mQueue = queue;
}
/**
* Forces this thread to quit immediately. If any requests are still in
* the queue, they are not guaranteed to be processed.
*/
public void quit()
{
mQuit = true;
interrupt();
}
#Override
public void run()
{
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
ImageData data;
while (true)
{
try
{
// Take a request from the queue.
data = mQueue.take();
}
catch (InterruptedException e)
{
// We may have been interrupted because it was time to quit.
if (mQuit)
{
return;
}
continue;
}
...
//other unrelated stuff
}
}
}

How to notify all observers without holding the thread?

I have a thread inside a class like this-
import java.util.Observable;
public class Download extends Observable {
private int state = 0;
private final Thread myThread = new Thread(() -> {
/*
some work to do here
*/
setChanged();
notifyObservers(state);
});
public void download(int state) {
if (!myThread.isAlive()) {
this.state = state;
myThread.start();
}
}
public Thread getThread() {
return myThread;
}
public static void MyMethod() throws InterruptedException {
Download down = new Download();
down.addObserver((Observable ob, Object dat) -> {
System.out.println(ob);
if ((int) dat == 1) {
down.download(2);
} else {
System.out.println("success");
}
});
down.download(1);
down.getThread().join();
}
public static void main() throws InterruptedException {
MyMethod();
}
}
The problem is I never get it to print the "success" message.
I assume, it is because all observers are being notified from inside of MyThread. So when down.download(2) is called from the observer inside MyMethod(), the previous thread is still running and the call is ignored.
How can I notify all observers from the main thread, not from the myThread?
You are calling down.download(2) from within the execution of MyThread, therefore the thread is still alive which means that your download method does nothing because of if(!myThread.isAlive()).
I would recommend you to use the Executor framework and Listenable Futures from Guava instead of creating threads manually. Example code from the Guava wiki:
ListeningExecutorService service =
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Explosion> explosion = service.submit(new Callable<Explosion>() {
public Explosion call() {
return pushBigRedButton();
}
});
Futures.addCallback(explosion, new FutureCallback<Explosion>() {
// we want this handler to run immediately after we push the big red button!
public void onSuccess(Explosion explosion) {
walkAwayFrom(explosion);
}
public void onFailure(Throwable thrown) {
battleArchNemesis(); // escaped the explosion!
}
});
Note that Futures.addCallback(..) also has an overload which allows you to determine which executor should execute the callback, this seems to be what you want.

Categories