This Confluence has been LDAP enabled, if you are an ASF Committer, please use your LDAP Credentials to login. Any problems file an INFRA jira ticket please.

Skip to end of metadata
Go to start of metadata

Invokers allow you to customise how a particular method is executed. This is particular useful if your underlying service objects are not plain javabeans and instead need to be created or looked up via a custom factory.

CXF does provide a number of bundled invokers to handle simple cases. One of these simple cases is when it is desirable to have a singleton for the service object. In this case, you would like to provide a single object instance that should be used for all service invocations. The provided BeanInvoker covers this functionality, and would be used as follows:

Service service = ...; 
service.setInvoker(new BeanInvoker(new MyCustomBean(someParams)));

You can access the underlying Service object in two ways. If you've created your service using a ServerFactoryBean, this will yield a Server object which can be used to gain access to the Service:

ServerFactoryBean factory = new ServerFactoryBean();
....
Server server = factory.create()
Service service = server.getEndpoint().getService();

If you've created a JAX-WS Endpoint object, you can access the Service like this:

EndpointImpl endpoint = (EndpointImpl) Endpoint.publish("http://host/service", new MyService());
....
Server server = endpoint.getServer();
Service service = server.getEndpoint().getService();

The following example illustrates how an invoker can be used to allow CXF to expose remote stateless session beans as a webservice. Given the method to invoke, this invoker will create a stateless session bean instance to invoke the method on. The same technique can be used to enable service calls to any object that requires custom creation/lookup.

The invoker implementation is as follows:

public class EJBInvoker extends AbstractInvoker
{
  private EJBHome home;
  private Method createMethod;
  private static final Object[] EMPTY_OBJECT = new Object[0];

  public EJBInvoker(EJBHome home)
  {
    this.home = home;
    try
    {
      if(!home.getEJBMetaData().isSession() || !home.getEJBMetaData().isStatelessSession())
      {
        throw new IllegalArgumentException("home must be for a stateless session bean");
      }
      createMethod = home.getClass().getMethod("create", new Class[0]);
    }
    catch(Exception ex)
    {
      throw new IllegalArgumentException("Unable to initialize invoker: " + ex);
    }
  }

  public Object getServiceObject(final Exchange context)
  {
     return createMethod.invoke(home, EMPTY_OBJECT);
  }
}

Invokers, once defined, need to be registered with the Service. Once a handle onto a Service object has been obtained, the example invoker above can be registered on the binding like this:

Service ejbService = ....;
ejbService.setInvoker(new EJBInvoker(ejbHome));

If you are using an EJB3 container you can use the following invoker, which is just a simplified version of the above:

public class EJB3Invoker extends AbstractInvoker {
    private Object ejb;

    public EJB3Invoker(String jndiName) throws NamingException 	{
        ejb = new InitialContext().lookup(jndiName);
    }

    public Object getServiceObject(final Exchange context) {
        return ejb;
    }
}

Executors

In addition to providing your own Invokers, you can also supply Executors for your service. Executors are a way to control scheduling for your service. To supply your own executor for a service just do:

Service service = ....; // look up the service from CXF, or create it
service.setExecutor(new MyExecutor());
  • No labels