cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

We are happy to announce the new Windchill Customization board! Learn more.

remote method server exception querying WfProcess

aacciano-2
10-Marble

remote method server exception querying WfProcess

Hello Gurus.

I am trying to retrieve the global Process variables of a Change Notice from a Change Activity.

Running the code below I get the  following error:

CA is 07138

CN is 06489

Reference is  wt.change2.WTChangeOrder2>671258721

Object is  wt.change2.WTChangeOrder2:671258722

qrWfProc  wt.fc.QueryResult@5039f4d3

WARNING: The ManagerService is not initialized!  This can be caused by:

1) Attempting to invoke a server only method from a remote client

2) Attempting to invoke a method on a service from the constructor or static initializer of another service

Exception in thread "main" java.lang.ExceptionInInitializerError

at wt.workflow.engine.WfProcess.getName(WfProcess.java:1425)

at wt.workflow.engine.WfExecutionObject.toString(WfExecutionObject.java:710)

at wt.workflow.engine.WfProcess.toString(WfProcess.java:296)

at java.lang.String.valueOf(Unknown Source)

at java.lang.StringBuilder.append(Unknown Source)

at ext.ChangeNotice2.main(ChangeNotice2.java:47)

Caused by: java.lang.NullPointerException

at wt.access.AccessControlServerHelper.<clinit>(AccessControlServerHelper.java:77)

... 6 more

The code that I used is:

package ext;

import wt.change2.ChangeHelper2;
import wt.change2.WTChangeActivity2;
import wt.change2.WTChangeOrder2;
import wt.fc.ObjectIdentifier;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.fc.ReferenceFactory;
import wt.fc.WTReference;
import wt.method.RemoteAccess;
import wt.method.RemoteMethodServer;
import wt.util.WTException;
import wt.workflow.engine.WfProcess;
import wt.workflow.engine.WfVariable;

public class ChangeNotice2 implements RemoteAccess {

public static void main(String[] args) throws WTException {
  // TODO Auto-generated method stub
 
  RemoteMethodServer rms = RemoteMethodServer.getDefault();
  rms.setUserName("wcadmin");
  rms.setPassword("wcadmin");

  ObjectIdentifier oid = ObjectIdentifier.newObjectIdentifier("wt.change2.WTChangeActivity2:671258847");
  WTChangeActivity2 ecaOID = (WTChangeActivity2) PersistenceHelper.manager.refresh(oid);
  System.out.println("CA is " + ecaOID.getNumber());

  QueryResult qr = ChangeHelper2.service.getChangeOrder(ecaOID);
  while (qr.hasMoreElements()) {
   Object obj = qr.nextElement();
   if (obj instanceof WTChangeOrder2) {
    WTChangeOrder2 ecn = (WTChangeOrder2) obj;
    System.out.println("CN is " + ecn.getNumber());
    ReferenceFactory rf = new ReferenceFactory();
    WTReference ref = (WTReference) rf.getReference(ecn);
    System.out.println("Reference is  " + ref);
    System.out.println("Object is  " + ref.getObject());
    WTChangeOrder2 wtChangeOrder = (WTChangeOrder2) ref.getObject();

    QueryResult qrWfProc =  wt.workflow.engine.WfEngineHelper.service.getAssociatedProcesses(wtChangeOrder, null, wtChangeOrder.getContainerReference());
    System.out.println("qrWfProc  " + qrWfProc);
    while (qrWfProc.hasMoreElements()) {
    
      WfProcess process = (WfProcess) qrWfProc.nextElement();
      System.out.println("Process is " + process);
      WfVariable vars[] = process.getContext().getVariableList();
      for (WfVariable var : vars) {
       System.out.println("Printing Variable " + var.getName() + "---value---" + var.getValue());
      }
    }
   }
  }

}

Any help will be appreciated

Thanks

Antonio

1 ACCEPTED SOLUTION

Accepted Solutions

Hi Antonio,

The code is  supposed to be executed in the Method Server, though in your code you have created the instance of the method server, but you are not using it.

String argType={String.class};

String argValue={"wt.change2.WTChangeActivity2:671258847"}; // pass oid as string

RemoteMethodServer.getDefault().invoke( "<method_name>", "<class_name>", null, argType, argValue);

Note:- this class must implement RemoteAccess interface.

Place the following code in a separate method, and invoke that method from mains, using RMI call as mentioned above.

ObjectIdentifier oid = ObjectIdentifier.newObjectIdentifier("wt.change2.WTChangeActivity2:671258847");

  WTChangeActivity2 ecaOID = (WTChangeActivity2) PersistenceHelper.manager.refresh(oid);

  System.out.println("CA is " + ecaOID.getNumber()); 

  QueryResult qr = ChangeHelper2.service.getChangeOrder(ecaOID);
  while (qr.hasMoreElements()) {
   Object obj = qr.nextElement();
   if (obj instanceof WTChangeOrder2) {
    WTChangeOrder2 ecn = (WTChangeOrder2) obj;
    System.out.println("CN is " + ecn.getNumber());
    ReferenceFactory rf = new ReferenceFactory();
    WTReference ref = (WTReference) rf.getReference(ecn);
    System.out.println("Reference is  " + ref);
    System.out.println("Object is  " + ref.getObject());
    WTChangeOrder2 wtChangeOrder = (WTChangeOrder2) ref.getObject();

    QueryResult qrWfProc =  wt.workflow.engine.WfEngineHelper.service.getAssociatedProcesses(wtChangeOrder, null, wtChangeOrder.getContainerReference());
    System.out.println("qrWfProc  " + qrWfProc);
    while (qrWfProc.hasMoreElements()) {
    
      WfProcess process = (WfProcess) qrWfProc.nextElement();
      System.out.println("Process is " + process);
      WfVariable vars[] = process.getContext().getVariableList();
      for (WfVariable var : vars) {
       System.out.println("Printing Variable " + var.getName() + "---value---" + var.getValue());
      }
    }
   }

Thanks,

Aditya

View solution in original post

5 REPLIES 5

Hi Antonio,

The code is  supposed to be executed in the Method Server, though in your code you have created the instance of the method server, but you are not using it.

String argType={String.class};

String argValue={"wt.change2.WTChangeActivity2:671258847"}; // pass oid as string

RemoteMethodServer.getDefault().invoke( "<method_name>", "<class_name>", null, argType, argValue);

Note:- this class must implement RemoteAccess interface.

Place the following code in a separate method, and invoke that method from mains, using RMI call as mentioned above.

ObjectIdentifier oid = ObjectIdentifier.newObjectIdentifier("wt.change2.WTChangeActivity2:671258847");

  WTChangeActivity2 ecaOID = (WTChangeActivity2) PersistenceHelper.manager.refresh(oid);

  System.out.println("CA is " + ecaOID.getNumber()); 

  QueryResult qr = ChangeHelper2.service.getChangeOrder(ecaOID);
  while (qr.hasMoreElements()) {
   Object obj = qr.nextElement();
   if (obj instanceof WTChangeOrder2) {
    WTChangeOrder2 ecn = (WTChangeOrder2) obj;
    System.out.println("CN is " + ecn.getNumber());
    ReferenceFactory rf = new ReferenceFactory();
    WTReference ref = (WTReference) rf.getReference(ecn);
    System.out.println("Reference is  " + ref);
    System.out.println("Object is  " + ref.getObject());
    WTChangeOrder2 wtChangeOrder = (WTChangeOrder2) ref.getObject();

    QueryResult qrWfProc =  wt.workflow.engine.WfEngineHelper.service.getAssociatedProcesses(wtChangeOrder, null, wtChangeOrder.getContainerReference());
    System.out.println("qrWfProc  " + qrWfProc);
    while (qrWfProc.hasMoreElements()) {
    
      WfProcess process = (WfProcess) qrWfProc.nextElement();
      System.out.println("Process is " + process);
      WfVariable vars[] = process.getContext().getVariableList();
      for (WfVariable var : vars) {
       System.out.println("Printing Variable " + var.getName() + "---value---" + var.getValue());
      }
    }
   }

Thanks,

Aditya

Hi Aditya,

Thank you so very much!

That helped a lot to find the issue!!

I do have additional question for you.

1) If I place the code inside an expression robot in a workflow, I imagine I can remove the remote method server call, correct?

2) If I use an expression robot to call the class with my code, do I still need to have the instantiation of the MS or can I call the code method directly?

Sorry for the silly questions..

I am very new to java and customization, even though I am long time Windchill Admin.

Thank you very much for your help!

Antonio

Hi Antonio,

You are correct, its not required to instantiate MS for both the cases you have mentioned.

Expression robot has limitions on number of line of code, so its always recommended to make a method call to a custom workflow helper class(Use case 2) from the expression.

thanks,

Aditya

jessh
5-Regular Member
(To:asingh)

More generally if your code is being invoked within a method server, whether it is by a workflow, a JSP page (in 10.0 or higher where Tomcat is embedded in the method server), or whatever, then you not only do not need to use RemoteMethodServer.invoke(), but you should not use it -- as it causes a loopback RMI request which is wasteful.  Moreover, you'll get warnings in recent Windchill versions if you do this.

If you have code which may or may not be in the method server you can use *Helper.manager.* or *Helper.service.* methods or you can logic like they do internally:

if (RemoteMethodServer.ServerFlag) {

  // call code directly, you're in a method server

} else {

  // do RemoteMethodServer.invoke() -- as you're not in a method server

}

Finally, I should note that if you have code that may be running in a server manager, then you should not blithely assume you can do RemoteMethodServer.invoke() -- at least not if you have any cluster nodes that do not have (and should not have) a foreground method server -- as RemoteMethodServer.invoke() requires a foreground method server.  This issue most frequently comes up from custom wt.cache.CacheManager subclasses that do not consider how their methods are called in server managers.

Aditya,

Thanks again for your help, I really appreciate it.

Jess,

awesome explanation.

Thank you!

Top Tags