Add a progress bar to a Job in RCP - java

I have a time consuming job in my RCp application in which I read out a big database and save it in a file. I am running this job in a separate thread so that the UI of my app is not blocked but I dont know how to add a progress bar to this task
My code:
public class MirrorFeatureModel extends Job {
protected class MutexRule implements ISchedulingRule {
public boolean isConflicting(ISchedulingRule rule) {
return rule == this;
}
public boolean contains(ISchedulingRule rule) {
return rule == this;
}
}
private String source;
private String template;
private String target;
public MirrorFeatureModel(String name) {
super(name);
}
public MirrorFeatureModel(String source, String template, String target){
super("Mirroring SWA Model");
this.source = source;
this.template = template;
this.target = target;
}
public void run() {
this.schedule();
}
#Override
protected IStatus run(IProgressMonitor monitor) {
ILog logView = Activator.getDefault().getLog();
String connectionString = this.source;
String emptyEAP = this.template;
String target = this.target;
try{
monitor.beginTask("Copying swa model to local", 1);
new Mirror(connectionString, emptyEAP,target).run();
monitor.worked(1);
}catch(final Exception e) {
logView.log(new Status(Status.ERROR, null , "Failed to create local SAM instance", e));
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run() {
MessageDialog.openError(PlatformUI.getWorkbench().getDisplay().getActiveShell(), "Failed to create local SAM instance", e.getMessage());
}
});
return Status.CANCEL_STATUS;
}
return Status.OK_STATUS;
}
}
Mirror.run() Method
public void run(IProgressMonitor monitor) {
try{
if (monitor != null)
monitor.subTask("Creating directory for eap file");
File tempTarget=File.createTempFile("eap-mirror", "eap");
if (monitor != null)
monitor.worked(1);
try {
if (monitor != null)
monitor.subTask("Establising connection");
this.source=DriverManager.getConnection(com.intel.imc.swa.easql.EaDbStringParser.eaDbStringToJdbc(sourceString));
this.source.setReadOnly(true);
if(monitor != null)
monitor.worked(1);
FileUtils.copyFile(new File(templateFileString), tempTarget);
if (monitor != null)
monitor.subTask("Opening database");
this.target=Database.open(tempTarget,false,false);
if(monitor != null)
monitor.worked(1);
if (monitor != null)
monitor.subTask("Mirroring tables");
Collection<String> tables=selectTables(source);
long time=System.currentTimeMillis();
for (String tableName : tables) {
long tTime=System.currentTimeMillis();
Table table=target.getTable(tableName);
System.out.print("Mirroring table "+tableName+"...");
table.setOverrideAutonumber(true);
copyTable(table, source, target);
System.out.println(" took "+(System.currentTimeMillis()-tTime));
}
System.out.println("Done. Overall time: "+(System.currentTimeMillis()-time));
if(monitor != null)
monitor.worked(1);
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
How can I add a progress bar in this class that shows me the progress of this job
Thanks

Normally jobs show a progress indicator in the progress view and in the status line at the bottom of the main window.
If you call setUser(true) before schedule() then the job will show a pop-up progress dialog if the job runs for more than a few seconds.
To show job progress you must specify the total amount of work on the beginTask call
monitor.beginTask("...", total work);
and then you must call monitor.worked(xxx) each time you have done part of the work.

Related

Java two threads work with the same data (one get, one set)

I'm taking my first steps with Java Sockets and Threads.
I want to try make synchonized connection with serwer where multiple threades adds their request to the queue and signle thread send all this request. In the meantime other threads wait for there resoults.
How it's work:
Client ask servert to log in by caling method
User user = logIn("sdasd");
public User logIn(String name){
System.out.println("!Log in");
//Function create request
RequestHandler<User> request = new RequestHandler<>("logIn", name, out, results);
//Request is added to queue
requestQueue.addLast(request);
RequestStatus status;
//Thread who call this function wait for request to be handle (changed status)
while (true){
status = request.getStatus();
System.out.println(status);
if (status == RequestStatus.SUCCESSFUL) {
System.out.println("Try to get result: ");
User user = request.result();
System.out.println(user.getName());
return request.result();
}
if(status == RequestStatus.FAILED) {
return null;
}
}
}
In the meantime other thread send request to server:
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()){
//is request to be handle?
if(requestQueue.size() != 0){
//remove request form queue
RequestHandler request = (RequestHandler) requestQueue.removeFirst();
//change request status
request.setStatus(RequestStatus.IN_PROGRESS);
System.out.println("!Request: ");
System.out.println(request.getStatus());
//process request
request.request();
//change request status to finished
request.setStatus(RequestStatus.SUCCESSFUL);
System.out.print("!Request end: ");
System.out.println(request.getStatus());
}
}
Iterator<Request> iterator = requestQueue.iterator();
for (Iterator<Request> it = iterator; it.hasNext(); ) {
Request request = it.next();
request.setStatus(RequestStatus.FAILED);
}
}
}).start();
Inside class RequestHandler is process this code:
#Override
public void request() {
try {
//send commend
out.writeObject(requestCommend);
//wait for result (other thread handle this functionality)
while(!results.containsKey(commend)){}
//attach result
result = (T) results.remove(commend);
} catch (IOException e) {
e.printStackTrace();
}
}
When the request is send to the server other thread wait for response for the server and add result to the HashMap:
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()) {
try {
String commend = (String) in.readObject();
if(commend.charAt(0) == '#') { // # mean its result of request
Object object = in.readObject();
//This is debug case to see everything work properly
if(object == null){
System.out.println("!I am null");
}else{
System.out.println("I am user: " +((User) object).getName());
}
System.out.println(commend);
results.put(commend, object);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}).start();
This is it. Required code for this question:
public class ServerConnection extends Socket{
public static final int PORT = 8888;
private ObjectInputStream in;
private ObjectOutputStream out;
private LinkedList<Request> requestQueue;
private ConcurrentHashMap<String, Object> results;
public ServerConnection() throws IOException{
super("localhost", PORT);
System.out.println("Connected to the server.");
in = new ObjectInputStream(getInputStream());
out = new ObjectOutputStream(getOutputStream());
requestQueue = new LinkedList<>();
results = new ConcurrentHashMap<>();
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()){
if(requestQueue.size() != 0){
RequestHandler request = (RequestHandler) requestQueue.removeFirst();
request.setStatus(RequestStatus.IN_PROGRESS);
System.out.println("!Request: ");
System.out.println(request.getStatus());
request.request();
request.setStatus(RequestStatus.SUCCESSFUL);
System.out.print("!Request end: ");
System.out.println(request.getStatus());
}
}
Iterator<Request> iterator = requestQueue.iterator();
for (Iterator<Request> it = iterator; it.hasNext(); ) {
Request request = it.next();
request.setStatus(RequestStatus.FAILED);
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()) {
try {
String commend = (String) in.readObject();
if(commend.charAt(0) == '#') { // # mean its result of request
Object object = in.readObject();
//This is debug case
if(object == null){
System.out.println("!I am null");
}else{
System.out.println("I am user: " +((User) object).getName());
}
System.out.println(commend);
results.put(commend, object);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}).start();
}
public User logIn(String name){
System.out.println("!Log in");
RequestHandler<User> request = new RequestHandler<>("logIn", name, out, results);
requestQueue.addLast(request);
RequestStatus status;
while (true){
status = request.getStatus();
System.out.println(status);
if (status == RequestStatus.SUCCESSFUL) {
System.out.println("Try to get result: ");
User user = request.result();
System.out.println(user.getName());
return request.result();
}
if(status == RequestStatus.FAILED) {
return null;
}
}
}
public ArrayList<Room> getListOfRooms(){
Request<ArrayList<Room>> request = new RequestHandler<>("listOfRooms", out, results);
requestQueue.addLast(request);
while (true){
RequestStatus status = request.getStatus();
if (status == RequestStatus.SUCCESSFUL)
return request.result();
if(status == RequestStatus.FAILED) {
return null;
}
}
}
}
RequestHandler looks like this:
public class RequestHandler<T> implements Request<T>{
private T result;
private RequestStatus status = RequestStatus.NEW;
private ObjectOutputStream out;
private String commend;
private String requestCommend;
private ConcurrentHashMap<String, Object> results;
public RequestHandler(String commend, String parameters, ObjectOutputStream out, ConcurrentHashMap<String, Object> results) {
this.commend = "#" + commend;
this.requestCommend = "?" + commend + ":" + parameters;
this.out = out;
this.results = results;
}
public RequestHandler(String commend, ObjectOutputStream out, ConcurrentHashMap<String, Object> results) {
this.commend = "#" + commend;
this.requestCommend = "?" + commend;
this.out = out;
this.results = results;
}
#Override
public void request() {
try {
out.writeObject(requestCommend);
while(!results.containsKey(commend)){}
result = (T) results.remove(commend);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public T result() {
return result;
}
#Override
public RequestStatus getStatus() {
return status;
}
#Override
public void setStatus(RequestStatus status) {
this.status = status;
}
}
The output looks like this WHEN ITS WORK:
Connected to the server.
!Log in
NEW
IN_PROGRESS
...
IN_PROGRESS
!Request: IN_PROGRESS
IN_PROGRESS
...
IN_PROGRESS
I am user: sdsad
#logIn
IN_PROGRESS
IN_PROGRESS
SUCCESSFUL
!Request end: SUCCESSFUL
Try to get result:
sdsad
But when I COMMENT one debug msg I got this:
Connected to the server.
!Log in
!Request: IN_PROGRESS
I am user: dfdsfsdf4324
#logIn
!Request end: SUCCESSFUL
And the loop while(true) never end becouse I got always status IN_PROGRESS.
That's why I want to ask you why it's happen? Is Java have some weird way to optimalize output of functions to make is faster and is it thinking if it was reapet milion times so it has to be this state always?

Semaphore does not invoke release()

I have implemented a thread in an Android app that is invoked every minute, the invocation of the process occur through an Alarm Manager.
#Override
public void onReceive(Context context, Intent intent) {
try {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock;
if (powerManager != null) {
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Send-data");
wakeLock.acquire(10 * 60 * 1000L);
new Thread(new SendPolicyData(context)).start();
wakeLock.release();
}
} catch (Exception e) {
wil.WriteFile("1)AlarmSendData - Exception: " + e.toString());
}
}
The code contained in the thread extract a set of data from a database that must be sent through posts to a server, the access to resources is controlled via a semaphore.
#SuppressWarnings("ResultOfMethodCallIgnored")
public class SendPolicyData implements Runnable {
private static final WriteInLogFile wil = new WriteInLogFile();
private final Context ctx;
public SendPolicyData(Context ctx) {
this.ctx = ctx;
}
public void run() {
try {
SemaphoreDTS.getInstance().goIn();
Authentication singleCall = new Authentication();
Utilities utilities = new Utilities(ctx);
DbGest dbGest = DbGest.getInstance(ctx);
if (utilities.checkConnection()) {
int lastProcessedID = -1;
int attempts = 0;
Cursor cursor = dbGest.freeQuery("SELECT id, label, value, priority FROM " + TABLE_DATATOSEND + " ORDER BY priority,dateIns");
if (cursor != null) {
cursor.moveToFirst();
if (cursor.getCount() > 0) {
do {
int toProcessID = cursor.getInt(cursor.getColumnIndex("id"));
String value = cursor.getString(cursor.getColumnIndex("value"));
String labelString = cursor.getString(cursor.getColumnIndex("label"));
if (lastProcessedID == toProcessID) {
if (attempts <= 5) {
attempts++;
Thread.sleep(3000);
} else {
attempts = 0;
dbGest.changeDTSRecordPriority(toProcessID);
}
}
switch (labelString) {
case "photo":
//DO STUFF
break;
lastProcessedID = toProcessID;
} while (cursor.moveToNext());
}
cursor.close();
}
}
} catch (Exception e) {
SemaphoreDTS.getInstance().goOut();
wil.WriteFile("7)SendPolicyData - Exception: " + e.toString());
} finally {
SemaphoreDTS.getInstance().goOut();
}
SemaphoreDTS.getInstance().goOut();
}
}
This is the source code of the semaphore that I use to manage the access to the resources.
public class SemaphoreDTS {
private static SemaphoreDTS instance;
private final Semaphore semaphore;
private final WriteInLogFile wil = new WriteInLogFile();
private SemaphoreDTS() {
this.semaphore = new Semaphore(1, true);
}
public static SemaphoreDTS getInstance() {
if (instance == null) {
instance = new SemaphoreDTS();
}
return instance;
}
public synchronized void goIn() {
try {
semaphore.acquire();
} catch (Exception e) {
wil.WriteFile("1)SemaphoreDTS - Exception: " + e.toString());
}
}
public synchronized void goOut() {
try {
semaphore.release();
} catch (Exception e) {
wil.WriteFile("2)SemaphoreDTS - Exception: " + e.toString());
}
}
}
During the tests that I did, it often happens that the semaphore remains blocked, for some reason the necessary release is not invoked in order to be able to perform new acquire.
I think I have written the code correctly and I don't understand where I am wrong.
In this code's block:
catch (Exception e) {
SemaphoreDTS.getInstance().goOut();
wil.WriteFile("7)SendPolicyData - Exception: " + e.toString());
} finally {
SemaphoreDTS.getInstance().goOut();
}
SemaphoreDTS.getInstance().goOut();
You always have two calls .goOut(), because finally block always will invoke.
When you call .release() (in your method .goOut()) semaphore gets availible permit, i.e instead 1 permit your semaphore gets 2 permits. I think problem starts here. Try to delete calls `.goOut() method everywhere but not in finally()

Preventing thread from duplicate processing in java

Problem statement
I have a JMS listener running as a thread listening to a topic. As soon a message comes in, I spawn a new Thread to process the in-bounded message. So for each incoming message I spawn a new Thread.
I have a scenario where duplicate message is also being processed when it is injected immediately in a sequential order. I need to prevent this from being processed. I tried using a ConcurrentHashMap to hold the process times where I add in the entry as soon as Thread is spawn and remove it from the map as soon Thread completes its execution. But it did not help when I tried with the scenario where I passed in same one after the another in concurrent fashion.
General Outline of my issue before you plunge into the actual code base
onMessage(){
processIncomingMessage(){
ExecutorService executorService = Executors.newFixedThreadPool(1000);
//Map is used to make an entry before i spawn a new thread to process incoming message
//Map contains "Key as the incoming message" and "value as boolean"
//check map for duplicate check
//The below check is failing and allowing duplicate messages to be processed in parallel
if(entryisPresentInMap){
//return doing nothing
}else{
//spawn a new thread for each incoming message
//also ensure a duplicate message being processed when it in process by an active thread
executorService.execute(new Runnable() {
#Override
public void run() {
try {
//actuall business logic
}finally{
//remove entry from the map so after processing is done with the message
}
}
}
}
Standalone example to mimic the scenario
public class DuplicateCheck {
private static Map<String,Boolean> duplicateCheckMap =
new ConcurrentHashMap<String,Boolean>(1000);
private static String name=null;
private static String[] nameArray = new String[20];
public static void processMessage(String message){
System.out.println("Processed message =" +message);
}
public static void main(String args[]){
nameArray[0] = "Peter";
nameArray[1] = "Peter";
nameArray[2] = "Adam";
for(int i=0;i<=nameArray.length;i++){
name=nameArray[i];
if(duplicateCheckMap.get(name)!=null && duplicateCheckMap.get(name)){
System.out.println("Thread detected for processing your name ="+name);
return;
}
addNameIntoMap(name);
new Thread(new Runnable() {
#Override
public void run() {
try {
processMessage(name);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
freeNameFromMap(name);
}
}
}).start();
}
}
private static synchronized void addNameIntoMap(String name) {
if (name != null) {
duplicateCheckMap.put(name, true);
System.out.println("Thread processing the "+name+" is added to the status map");
}
}
private static synchronized void freeNameFromMap(String name) {
if (name != null) {
duplicateCheckMap.remove(name);
System.out.println("Thread processing the "+name+" is released from the status map");
}
}
Snippet of the code is below
public void processControlMessage(final Message message) {
RDPWorkflowControlMessage rdpWorkflowControlMessage= unmarshallControlMessage(message);
final String workflowName = rdpWorkflowControlMessage.getWorkflowName();
final String controlMessageEvent=rdpWorkflowControlMessage.getControlMessage().value();
if(controlMessageStateMap.get(workflowName)!=null && controlMessageStateMap.get(workflowName)){
log.info("Cache cleanup for the workflow :"+workflowName+" is already in progress");
return;
}else {
log.info("doing nothing");
}
Semaphore controlMessageLock = new Semaphore(1);
try{
controlMessageLock.acquire();
synchronized(this){
new Thread(new Runnable(){
#Override
public void run() {
try {
lock.lock();
log.info("Processing Workflow Control Message for the workflow :"+workflowName);
if (message instanceof TextMessage) {
if ("REFRESH".equalsIgnoreCase(controlMessageEvent)) {
clearControlMessageBuffer();
enableControlMessageStatus(workflowName);
List<String> matchingValues=new ArrayList<String>();
matchingValues.add(workflowName);
ConcreteSetDAO tasksSetDAO=taskEventListener.getConcreteSetDAO();
ConcreteSetDAO workflowSetDAO=workflowEventListener.getConcreteSetDAO();
tasksSetDAO.deleteMatchingRecords(matchingValues);
workflowSetDAO.deleteMatchingRecords(matchingValues);
fetchNewWorkflowItems();
addShutdownHook(workflowName);
}
}
} catch (Exception e) {
log.error("Error extracting item of type RDPWorkflowControlMessage from message "
+ message);
} finally {
disableControlMessageStatus(workflowName);
lock.unlock();
}
}
}).start();
}
} catch (InterruptedException ie) {
log.info("Interrupted Exception during control message lock acquisition"+ie);
}finally{
controlMessageLock.release();
}
}
private void addShutdownHook(final String workflowName) {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
disableControlMessageStatus(workflowName);
}
});
log.info("Shut Down Hook Attached for the thread processing the workflow :"+workflowName);
}
private RDPWorkflowControlMessage unmarshallControlMessage(Message message) {
RDPWorkflowControlMessage rdpWorkflowControlMessage = null;
try {
TextMessage textMessage = (TextMessage) message;
rdpWorkflowControlMessage = marshaller.unmarshalItem(textMessage.getText(), RDPWorkflowControlMessage.class);
} catch (Exception e) {
log.error("Error extracting item of type RDPWorkflowTask from message "
+ message);
}
return rdpWorkflowControlMessage;
}
private void fetchNewWorkflowItems() {
initSSL();
List<RDPWorkflowTask> allTasks=initAllTasks();
taskEventListener.addRDPWorkflowTasks(allTasks);
workflowEventListener.updateWorkflowStatus(allTasks);
}
private void clearControlMessageBuffer() {
taskEventListener.getRecordsForUpdate().clear();
workflowEventListener.getRecordsForUpdate().clear();
}
private synchronized void enableControlMessageStatus(String workflowName) {
if (workflowName != null) {
controlMessageStateMap.put(workflowName, true);
log.info("Thread processing the "+workflowName+" is added to the status map");
}
}
private synchronized void disableControlMessageStatus(String workflowName) {
if (workflowName != null) {
controlMessageStateMap.remove(workflowName);
log.info("Thread processing the "+workflowName+" is released from the status map");
}
}
I have modified my code to incorporate suggestions provided below but still it is not working
public void processControlMessage(final Message message) {
ExecutorService executorService = Executors.newFixedThreadPool(1000);
try{
lock.lock();
RDPWorkflowControlMessage rdpWorkflowControlMessage= unmarshallControlMessage(message);
final String workflowName = rdpWorkflowControlMessage.getWorkflowName();
final String controlMessageEvent=rdpWorkflowControlMessage.getControlMessage().value();
if(controlMessageStateMap.get(workflowName)!=null && controlMessageStateMap.get(workflowName)){
log.info("Cache cleanup for the workflow :"+workflowName+" is already in progress");
return;
}else {
log.info("doing nothing");
}
enableControlMessageStatus(workflowName);
executorService.execute(new Runnable() {
#Override
public void run() {
try {
//actual code
fetchNewWorkflowItems();
addShutdownHook(workflowName);
}
}
} catch (Exception e) {
log.error("Error extracting item of type RDPWorkflowControlMessage from message "
+ message);
} finally {
disableControlMessageStatus(workflowName);
}
}
});
} finally {
executorService.shutdown();
lock.unlock();
}
}
private void addShutdownHook(final String workflowName) {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
disableControlMessageStatus(workflowName);
}
});
log.info("Shut Down Hook Attached for the thread processing the workflow :"+workflowName);
}
private synchronized void enableControlMessageStatus(String workflowName) {
if (workflowName != null) {
controlMessageStateMap.put(workflowName, true);
log.info("Thread processing the "+workflowName+" is added to the status map");
}
}
private synchronized void disableControlMessageStatus(String workflowName) {
if (workflowName != null) {
controlMessageStateMap.remove(workflowName);
log.info("Thread processing the "+workflowName+" is released from the status map");
}
}
This is how you should add a value to a map. This double checking makes sure that only one thread adds a value to a map at any particular moment of time and you can control the access afterwards. Remove all the locking logic afterwards. It is as simple as that
public void processControlMessage(final String workflowName) {
if(!tryAddingMessageInProcessingMap(workflowName)){
Thread.sleep(1000); // sleep 1 sec and try again
processControlMessage(workflowName);
return ;
}
System.out.println(workflowName);
try{
// your code goes here
} finally{
controlMessageStateMap.remove(workflowName);
}
}
private boolean tryAddingMessageInProcessingMap(final String workflowName) {
if(controlMessageStateMap .get(workflowName)==null){
synchronized (this) {
if(controlMessageStateMap .get(workflowName)==null){
controlMessageStateMap.put(workflowName, true);
return true;
}
}
}
return false;
}
Read here more for https://en.wikipedia.org/wiki/Double-checked_locking
The issue is fixed now. Many thanks to #awsome for the approach. It is avoiding the duplicates when a thread is already processing the incoming duplicate message. If no thread is processing then it gets picked up
public void processControlMessage(final Message message) {
try {
lock.lock();
RDPWorkflowControlMessage rdpWorkflowControlMessage = unmarshallControlMessage(message);
final String workflowName = rdpWorkflowControlMessage.getWorkflowName();
final String controlMessageEvent = rdpWorkflowControlMessage.getControlMessage().value();
new Thread(new Runnable() {
#Override
public void run() {
try {
if (message instanceof TextMessage) {
if ("REFRESH".equalsIgnoreCase(controlMessageEvent)) {
if (tryAddingWorkflowNameInStatusMap(workflowName)) {
log.info("Processing Workflow Control Message for the workflow :"+ workflowName);
addShutdownHook(workflowName);
clearControlMessageBuffer();
List<String> matchingValues = new ArrayList<String>();
matchingValues.add(workflowName);
ConcreteSetDAO tasksSetDAO = taskEventListener.getConcreteSetDAO();
ConcreteSetDAO workflowSetDAO = workflowEventListener.getConcreteSetDAO();
tasksSetDAO.deleteMatchingRecords(matchingValues);
workflowSetDAO.deleteMatchingRecords(matchingValues);
List<RDPWorkflowTask> allTasks=fetchNewWorkflowItems(workflowName);
updateTasksAndWorkflowSet(allTasks);
removeWorkflowNameFromProcessingMap(workflowName);
} else {
log.info("Cache clean up is already in progress for the workflow ="+ workflowName);
return;
}
}
}
} catch (Exception e) {
log.error("Error extracting item of type RDPWorkflowControlMessage from message "
+ message);
}
}
}).start();
} finally {
lock.unlock();
}
}
private boolean tryAddingWorkflowNameInStatusMap(final String workflowName) {
if(controlMessageStateMap.get(workflowName)==null){
synchronized (this) {
if(controlMessageStateMap.get(workflowName)==null){
log.info("Adding an entry in to the map for the workflow ="+workflowName);
controlMessageStateMap.put(workflowName, true);
return true;
}
}
}
return false;
}
private synchronized void removeWorkflowNameFromProcessingMap(String workflowName) {
if (workflowName != null
&& (controlMessageStateMap.get(workflowName) != null && controlMessageStateMap
.get(workflowName))) {
controlMessageStateMap.remove(workflowName);
log.info("Thread processing the " + workflowName+ " is released from the status map");
}
}

SWTException: Invalid thread access

I work on a wizard for creation of a java project and get a invalid thread access exception if I run it in the empty workspace for the first time. I try to implement my wizard similar to JavaProjectWizard, but I don't need the second page, so I try to perform finish from the first page and to initialize the second page in advance:
import org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageTwo;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
public class SomeNewWizard
extends Wizard
implements INewWizard {
private SomeWizardPageTwo javaWizardPageTwo;
#Override
public void addPages() {
if (javaWizardPageTwo == null)
someWizardPageTwo = new SomeWizardPageTwo(newSeeAppWizardPageOne);
}
#Override
public boolean performFinish() {
/*line 109*/someWizardPageTwo .createProvisonalProject();
final IWorkspaceRunnable op = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor)
throws CoreException, OperationCanceledException {
try {
someWizardPageTwo.performFinish(new SubProgressMonitor(monitor, 1));
}
catch (InterruptedException e) {
throw new OperationCanceledException(e.getMessage());
}
finally {
monitor.done();
}
}
};
try {
rule = null;
Job job = Job.getJobManager().currentJob();
if (job != null)
rule = job.getRule();
IRunnableWithProgress runnable = new IRunnableWithProgress() {
#Override
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
try {
JavaCore.run(op, rule, monitor);
}
catch (OperationCanceledException e) {
throw new InterruptedException(e.getMessage());
}
catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
};
getContainer().run(true, true, runnable);
}
catch (InvocationTargetException e) {
handleFinishException(getShell(), e);
return false;
}
catch (InterruptedException e) {
return false;
}
return true;
}
public class SomeWizardPageTwo
extends NewJavaProjectWizardPageTwo
{
private NewJavaProjectWizardPageOne mainPage;
public SomeWizardPageTwo(NewJavaProjectWizardPageOne mainPage)
{
super(mainPage);
this.mainPage = mainPage;
}
#Override
public IProject createProvisonalProject()
{
return super.createProvisonalProject();
}
#Override
protected IWizardContainer getContainer()
{
if (mainPage == null)
return null;
return mainPage.getWizard().getContainer();
}
}
The stacktrace can be found here.
The root of the issue seems that ImageDescriptorRegistry is created from the wrong thread because the corresponding IRunnableWithProgress runs forked. But I wonder why does it work for the normal JavaProjectWizard then? And the main question is: how to make it work for my wizard?
getContainer().run(true, true, runnable); causes the runnable to be executed in a separate thread. The first parameter fork is responsible therefore.
The call to javaWizardPageTwo.performFinish() atempts to access the UI thread and causes the invalid thread access exception.
If you set the fork parameter to false, the code will be executed on the current thread.
Why don't you call javaWizardPageTwo.performFinish() directly?
There is not a bug in Display.checkDevice.
Your call to NewJavaProjectWizardPageTwo.performFinish is running in a background thread, but the code is using ImageDescriptorRegistry which needs to be initialized on the User Interface thread.
This is intermittent because sometimes something else that you do will have already initialized the registry.

Java thread listener

I would like to create a runnable class which contain a list inside. While running, thread will listen to any list changes and process all elements inside. That's my idea.
Below is my code but it still doesn't execute process() when I add new element to list or list changed by . Please give me some help.
public class QueueService implements Runnable {
private List<Request> requestQueue;
public synchronized void add(Request request) {
if (requestQueue == null) {
requestQueue = new LinkedList<Request>();
}
requestQueue.add(request);
LOGGER.info("Added new request");
}
#Override
public void run() {
LOGGER.info("Queue started...");
while (true) {
if (requestQueue != null) {
process();
}
}
}
private synchronized void process() {
try {
Iterator<VMRequest> requests = requestQueue.iterator();
while(requests.hasNext()) {
Request req = requests.next();
// process each element and remove when done
}
} catch (Exception e) {
LOGGER.info(e.getMessage());
}
}
}

Categories