On Friday 15 October 2010 9:19:36 pm thegreatone wrote:
> This is close to what I want:
> 
> http://cxf.apache.org/docs/multiplexed-endpointreferences.html
> 
> Except the "Number" class isn't really stateful. It can get an instanceId
> from the message context. I guess you could use that to look into some kind
> of HashMap that contains the state data you need but that sounds fairly
> messy:

Well, normally that would be something like an accountId or something that 
would then be usable to populate whatever data is needed from the database or 
similar.

I just committed some changes that may make this possible.   To the 
SessionFactory, I added a flag to have it NOT create a new instance if there 
isn't one in the session.   Thus, some other event needs to bind an instance 
into the session.     I've included the code below.

Basically, it registers two endpoints up front: 
1) The Bank itself
2) A BankAccountImpl.   The BankAccountImpl has:
@FactoryType(value = FactoryType.Type.Session, args = {"false"})
which means something MUST bind it in before it's usable.   A client that 
doesn't have it bound into the session will get a Fault back.

In the Bank, it will verify username/etc... and create a BankAccountImpl and 
bind it into the session using the QName.

That said, this REALLY relies on the clients supporting sessions.  In JAX-WS a 
single proxy has to support a session, but accross proxies, there isn't really 
a way to do it.  I added code below to show how to do it with CXF.


The other way this is commonly done is to have the getAccount call do 
something like:

String address = "http://localhost:8080/Bank/Account/"; + accountId;
                            //or other random thing
Endpoint ep = Endpoint.publish(address, new BankAccount(....));
return ep.getEndpointReference();


That publishes the BankAccount on a URL and returns the reference to that to 
the client.    The PROBLEM with this is that there isn't really an easy way to 
cleanup that.   You could record the EndpointReference and add a "logout" or 
something that causes it to unpublish, but for people that don't logout, you'd 
need to do something.   Plus, you'd have to be careful of the URL's and such 
to make sure they are very discoverable.



-- 
Daniel Kulp
[email protected]
http://dankulp.com/blog



------------------------------------------------
@WebService(name = "BankAccount",
            targetNamespace = "http://bank.dankulp.com";)
public interface BankAccount {
    
    public double getBalance();
    public void deposit(double amount);
    public void withdraw(double amount);
    public String getAccountId();
}
------------------------------------------------
@WebService(name = "Bank",
            targetNamespace = "http://bank.dankulp.com";)
public interface Bank {
    
    W3CEndpointReference login(String username, String password);
}
------------------------------------------------
@WebService(name = "BankAccount",
            serviceName = "BankAccount",
            targetNamespace = "http://bank.dankulp.com";,
            endpointInterface = "com.dankulp.bank.BankAccount")
@FactoryType(value = FactoryType.Type.Session, args = {"false"})
public class BankAccountImpl implements BankAccount {
    String name;
    double balance;
    
    
    public BankAccountImpl() {
    }
    public BankAccountImpl(String name) {
        this.name = name;
    }
    
    public String getAccountId() {
        return name;
    }
    
    public double getBalance() {
        return balance;
    }
    public void deposit(double amount) {
        balance += amount;
    }
    public void withdraw(double amount) {
        balance -= amount;
    }
}
------------------------------------------------
@WebService(serviceName = "Bank",
            name = "Bank",
            targetNamespace = "http://bank.dankulp.com";)
public class BankImpl implements Bank {
    W3CEndpointReference ref;
    
    public BankImpl(W3CEndpointReference r) {
        ref = r;
    }
    
    public W3CEndpointReference login(String username, String password) {
        if ("dkulp".equals(username)) {
            BankAccount ac = new BankAccountImpl("dkulp");
            PhaseInterceptorChain.getCurrentMessage().getExchange().getSession()
                .put(new QName("http://bank.dankulp.com";, 
"BankAccount").toString(), ac);
            return ref;
        }
        return null;
    }

    public static void main(String args[]) throws Exception {
        JettyHTTPServerEngineFactory f = 
BusFactory.getDefaultBus().getExtension(JettyHTTPServerEngineFactory.class);
        if (f == null) {
            f = new JettyHTTPServerEngineFactory();
            BusFactory.getDefaultBus().setExtension(f, 
JettyHTTPServerEngineFactory.class);
        }
        
        f.createJettyHTTPServerEngine(8080, "http").setSessionSupport(true);
        
        Endpoint ep = Endpoint.publish("http://localhost:8080/BankAccount";, 
new BankAccountImpl());
        W3CEndpointReference er = 
(W3CEndpointReference)ep.getEndpointReference();
        Endpoint.publish("http://localhost:8080/Bank";, new BankImpl(er));
        
        
        Service service = Service.create(new 
URL("http://localhost:8080/Bank?wsdl";),
                                      new QName("http://bank.dankulp.com";, 
"Bank"));
        Service accService = Service.create(new 
URL("http://localhost:8080/BankAccount?wsdl";),
                                 new QName("http://bank.dankulp.com";, 
"BankAccount"));
        Bank bank = service.getPort(Bank.class);
        
((BindingProvider)bank).getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY,
 
Boolean.TRUE);
        EndpointReference ref = bank.login("dkulp", "foo");
        ref = bank.login("dkulp", "foo");
        BankAccount account = accService.getPort(ref, BankAccount.class);
        
((BindingProvider)account).getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY,
 
Boolean.TRUE);
        
        //copy the session cookies accross to the new proxy
        
((HTTPConduit)ClientProxy.getClient(account).getConduit()).getCookies().putAll(
            
((HTTPConduit)ClientProxy.getClient(bank).getConduit()).getCookies());
        
        System.out.println(account.getAccountId());
        System.out.println(account.getBalance());
        account.deposit(100.00d);
        System.out.println(account.getBalance());
        account.withdraw(50.00d);
        System.out.println(account.getBalance());
    }
}

Reply via email to