doInvoke service throwing Null pointer exception

Hi,
I am trying to invoke a service inside a thread class. But it is throwing “java.lang.nullpointerException” when doing so. When I try to invoke it without any thread implementation then it is working fine. But if i use thread implementation its throwing an exception.

Sample Code:

IDataCursor pipelineCursor = pipeline.getCursor();
try
{
FPImpServiceN m1=new FPImpServiceN();
Thread t1 =new Thread(m1);
t1.start();

}
catch(Exception e)
{
throw new ServiceException(e);
}
pipelineCursor.destroy();

Code in source:

static class FPImpServiceN implements Runnable
{
public void run()
{
try
{
NSName nsName = NSName.create( “threadsPOC.services:new_javaService” );
IData outputData = Service.doInvoke( nsName, null );
}
catch(Exception e)
{
com.wm.util.JournalLogger.log( com.wm.util.JournalLogger.INFO, com.wm.util.JournalLogger.FAC_FLOW_SVC, com.wm.util.JournalLogger.DEBUG, e);
}
}
}

Please let me know how i can I invoke a service inside thread class.

Which line of the code is the exception pointing to?

Now, if all you want is to execute a service in a separate thread, you could/should use Service.doThreadInvoke instead of creating your own thread. Easier and simpler.

Percio

Hi Castro,

Thanks for the reply. I am getting the exception at the following line.

IData outputData = Service.doInvoke( nsName, null );

My requirement is to kill the thread when the service which is invoked by doInvoke() function takes long time to run than the specified timeout. This doInvoke() function resides inside a thread class. So killing thread will kill the execution of the service.

If I use doThreadInvoke() function then that thread continues to run in the background even though the main service exists.

Have you tried passing it an empty pipeline instead of null?

Hi Castro,

yes i tried.

IData inputData = IDataFactory.create();
NSName nsName = NSName.create( “threadsPOC.services:new_javaService” );
IData outputData = Service.doInvoke( nsName, inputData );

getting same exception.

try
{
Service.doInvoke(ifc, svc, pipe);
}
catch(Exception e)
{
throw new ServiceException(e);
}

However we have a service in 9.0 and above, WmPublic - pub.flow:invokeService which uses Service.doInvoke. See if that will suffice your need.

Getting same error Mahesh. By the way I am using 8.2 version. Thanks for the reply.

If the code works fine when executed on the “main” thread but fails when executed on a new thread, then I assume that there is some thread local variable which is present on the main thread but lacks on your custom thread. Like session or something like that.

And: Killing a thread in Java is not a simple thing. The thread must cooperate for it to happen cleanly. So, as Percio Castro said, I’d use doThreadInvoke if only possible.

Hi fml2,

I think you are correct. I resolved this problem by using the follow solution in thread class.

                    NSName nsName = NSName.create( "threadsPOC.services:new_javaService" );
                    com.wm.app.b2b.server.User user =   com.wm.app.b2b.server.UserManager.getUser("Administrator");
		Session s = StateManager.createContext(0x7fffffffL, "system", user);
		s.setUser(user);
		s.clearModified(); 
		NSName nsName = NSName.create(serviceName); 
		outputData = s.invoke(user, nsName, null );
		StateManager.deleteContext(s.getSessionID());

The service which i wanted to invoke from thread class got invoked successfully.

But this implementation doesn’t working as per my requirement. The service which I invoked from thread class is running in the background even after killing the thread.

The service should also stop when I kill the thread but it is not happening so. Can you please help me how I can stop the service from executing.

Hello,

where did you get all those classes and methods from? I don’t know them.

How do you kill the thread? To my knowledge, killing a thread is not a simple thing. The java method executed on the thread should be programmed in a “cooperative” way and be ready for thread termination (and should exit then). You can call some java method to terminate the thread, but if the thread method is not programmed properly it will have no effect. This is the way I understand it.

Hi fml2,

Thanks for the reply. Those methods are present in

import com.wm.app.b2b.server.Session;
import com.wm.app.b2b.server.StateManager;

Regarding the approach i am using for killing the thread please go through the following code.

Main code:

IDataCursor pipelineCursor = pipeline.getCursor();
try
{
long timeout = 10000;
String serviceName = “threadsPOC.services:new_javaService”;
int i=0, startTimer=0;
FilePullImpService m1=new FilePullImpService(serviceName);

		Thread t1 =new Thread(m1);
		while(true)
		{				
			if(i==0)
			{
				i++;
				t1.start(); /* Invoking the thread class*/
				com.wm.util.JournalLogger.log( com.wm.util.JournalLogger.INFO, com.wm.util.JournalLogger.FAC_FLOW_SVC, com.wm.util.JournalLogger.DEBUG, "Thread Class Started");			
			}
			else if(startTimer < timeout)
			{
				IData status = m1.returnval(); /*check If Thread completed execution. If completed then status will not be null*/
				if(status != null)
				{
					IDataUtil.put( pipelineCursor, "output", status );
					break;
				}
				else
				{
					startTimer +=1000;
					t1.join(1000); /* wait for 1000 milli seconds for thread to get completed */
					System.out.println(startTimer);
				}					
			}
			else /*If timeout exceeded and thread failed to complete */
			{	
				System.out.println("Thread Faied To Complete Before Timeout");
				System.out.println("Status Of Thread Before Killing " + t1.getState());
				t1.stop(); /* Stop the thread */
				System.out.println("Status Of Thread After Killing " + t1.getState());
				IDataUtil.put( pipelineCursor, "output", null );
				break;
			}
		}
	}
	catch(Exception e)
	{
		throw new ServiceException(e);
	}
	pipelineCursor.destroy();

Code in Source Area:

static class FilePullImpService extends Thread
{
String serviceName;
IData outputData = null;
Session s = null;
FilePullImpService(String serviceName)
{
this.serviceName = serviceName;

	}
	public void run()
	{
		com.wm.util.JournalLogger.log( com.wm.util.JournalLogger.INFO, com.wm.util.JournalLogger.FAC_FLOW_SVC, com.wm.util.JournalLogger.DEBUG, "Inside Thread Class");
		try
		{
			com.wm.app.b2b.server.User user = com.wm.app.b2b.server.UserManager.getUser("Administrator");
			Session s = StateManager.createContext(0x7fffffffL, "System", user);
			s.setUser(user);
			s.clearModified(); 
			NSName nsName = NSName.create(serviceName); /* Invokes The flow/Java service for execution */				
			outputData = s.invoke(user, nsName, null );
			StateManager.deleteContext(s.getSessionID());
		}	
		catch(ThreadDeath e)
		{
			com.wm.util.JournalLogger.log( com.wm.util.JournalLogger.INFO, com.wm.util.JournalLogger.FAC_FLOW_SVC, com.wm.util.JournalLogger.DEBUG, "Caught Thread Death Exception"); 
		}
		catch(Exception e)
		{
			com.wm.util.JournalLogger.log( com.wm.util.JournalLogger.INFO, com.wm.util.JournalLogger.FAC_FLOW_SVC, com.wm.util.JournalLogger.DEBUG, "Exception Caught In Thread Class"); 
		}
		
	}
	public IData returnval()
	{
		return outputData;
	}
}

After Killing The thread i can able to see the server log “Caught Thread Death Exception”. But still the service which invoked through thread class continues to run in the background. I want to stop its execution when the thread got killed using t1.stop(). Please let me know if any suggestions or help for achieving this ?

Thanks,
vinodkumar

apologies small correction.

outputData = s.invoke(user, nsName, null ); /* Invokes The flow/Java service for execution */.

The above statement invokes the required flow or java service.

From the JavaDoc for ThreadDeath: “If ThreadDeath is caught by a method, it is important that it be rethrown so that the thread actually dies.”. Your code does not rethrow it.

Thanks for the reply fml2.

I have included the re-throw exception logic. Tough luck same thing happening again i.e the service which was invoked by thread class still running in the back ground even after the thread got killed.

catch(ThreadDeath e)
{
throw e;
}

Even If I don’t include the re-throw logic the status of the thread showing as terminated after I use t1.stop(). Please find the screen shot. Please let me know if you have any suggestions. All my one week effort got vein.

No, I don’t have any further suggestions without diving deep into it myself.

How do you know the service is still running?

Hi fml2,

In the screen shot which I have shared there is a message called “bye” at the end. If the invoked service runs completely then this log message will be displayed which conveys that the service still continues to run even the thread got killed.

Thanks,
vinodkumar.

Vinod,

You realize Thread.stop() is deprecated. It has been deprecated for a long while. Perhaps we should talk about your use case a little bit to understand the requirements. There should be a simpler solution.

Having said this, if you must go down this path and you’re going to use undocumented API’s anyway, then how about you just mimic the same thing that the IS does when Service.doThreadInvoke is called? You will learn that, internally, the API returns a thread ID that you should then be able to use to kill the thread via existing API’s (e.g. WmRoot’s wm.server.query:killThread and wm.server.query:interruptThread).

Percio

Hi Castro,

Thanks for the reply. Coming to my requirement,

  1. A Main Flow service will invoke the child service and starts the timer.
  2. The child service can be anything. It can be a service which will connect to a FTP server and then pull the files from server.
  3. If the timer equals to timeout (The maximum time for the child service to complete) then it has to terminate the child service to execute further even though the child service is in middle of pulling the files from server.

Please let me know if you want to further details about the requirement.

IData results = null;
com.wm.app.b2b.server.ServiceThread svcThread =Service.doThreadInvoke(“VINODPOC.services”,“javaService_A”,results);

Please let me know how to get the Thread id from this.

Hi Castro,

By any chance can you please help me getting the thread ID from doThreadInvoke() service and killing it with WM Root services.

Thanks,
vinodkumar.

First, I’ll say that I’m not sure you should be pursuing this solution. In 13+ years of working with webMethods, I haven’t had to programatically kill a thread. If we take the example that you provided, the pub.client:ftp and pub.client:login services come with a timeout parameter that should be used for this exact purpose. If you kill the thread, you may be left with a partially transferred file, an open connection, etc.

For the sake of discussion though, let’s entertain the idea. Behind the scenes, Service.doThreadInvoke works more or less by doing this:

ServiceThread thread = new ServiceThread(nsName, InvokeState.getCurrentSession(), input);
ThreadManager.runTarget(thread, time);

The runTarget method returns an ID. So you could save that ID and then call ThreadManager.interrupt(id) to attempt to interrupt the thread. However, this will not necessarily stop the thread (e.g. if your thread is stuck in a REPEAT loop or any code, for that matter, which is not checking the isInterrupted() flag.)

For that situation, your best bet may be to call WmRoot/wm.server.query:getThreadList, find the thread that you’re interested in killing, and then call WmRoot/wm.server.query:interruptThread and/or killThread. This mimics killing a thread from the Server > Statistics > System Threads page. The challenge here though is finding the exact thread to be killed since you could have multiple threads for the same service running. One way would be to look at the startedat date.

Percio