You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by thegreatone <lo...@hotmail.com> on 2010/10/14 23:01:38 UTC

Stateful web services with CXF

I was reading how to do stateful web services using Metro:

https://metro.dev.java.net/1.4/docs/statefulWebservice.html

It uses the @Stateful annotation and returns and endpoint to the user that
maintains the state.

I don't see how this can be done with CXF, or at least it's not documented
well.

In the application I'm writing the server portion will be CXF (running in
JBoss).

The clients can be anything but the big one is .net (C# / VB). 

If the stateful WS solution doesn't work with .net clients, it's useless to
me. None of the WS clients will be written with CXF.
-- 
View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3212822.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Stateful web services with CXF

Posted by Benson Margulies <bi...@gmail.com>.
I checked some more. It's a 'vendor extension'
(https://jax-ws.dev.java.net/nonav/jax-ws-21-ea2/docs/statefulWebservice.html).
 It's also tangled up with WS-A, and perhaps not everyone who needs
state wants that.

On Thu, Oct 14, 2010 at 5:59 PM, thegreatone <lo...@hotmail.com> wrote:
>
> The "solution" you provided seems like more of a work around than a real
> solution.
>
> Why doesn't CXF simply support the "@Stateful" annotation ?
> --
> View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3212882.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>

Re: Stateful web services with CXF

Posted by Benson Margulies <bi...@gmail.com>.
Well, @Stateful isn't in the JAX-WS 2.2 doc, and it isn't in JSR-181.
So, I *think* that it's local to Metro. If I'm wrong please correct
me.

On Thu, Oct 14, 2010 at 5:59 PM, thegreatone <lo...@hotmail.com> wrote:
>
> The "solution" you provided seems like more of a work around than a real
> solution.
>
> Why doesn't CXF simply support the "@Stateful" annotation ?
> --
> View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3212882.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>

Re: Stateful web services with CXF

Posted by thegreatone <lo...@hotmail.com>.
The "solution" you provided seems like more of a work around than a real
solution.

Why doesn't CXF simply support the "@Stateful" annotation ?
-- 
View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3212882.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Stateful web services with CXF

Posted by Daniel Kulp <dk...@apache.org>.
On Friday 15 October 2010 1:28:23 pm thegreatone wrote:
> CXF has almost no documentation on this important matter - I find that
> strange.

Well, partially cause the relevant specs we implement don't allow it.  The 
JAX-WS spec is specifically targetting singletons and that's generally how 
almost all webservices are created.   THat said, it is a gap.

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog

Re: Stateful web services with CXF

Posted by Benson Margulies <bi...@gmail.com>.
Well, importance is in the eye of the typist, since it's all volunteer.

I don't suppose I could interest you in filing an iCLA and adding some.


On Fri, Oct 15, 2010 at 1:28 PM, thegreatone <lo...@hotmail.com> wrote:
>
> CXF has almost no documentation on this important matter - I find that
> strange.
> --
> View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3214136.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>

Re: Stateful web services with CXF

Posted by thegreatone <lo...@hotmail.com>.
CXF has almost no documentation on this important matter - I find that
strange.
-- 
View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3214136.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Stateful web services with CXF

Posted by Daniel Kulp <dk...@apache.org>.
On Friday 15 October 2010 3:10:24 pm Daniel Kulp wrote:
> On Friday 15 October 2010 8:24:58 am Benson Margulies wrote:
> > If I needed some concept of sessions persisting across multiple calls,
> > what would I do?
> 
> Well, you can get the HTTPServletRequest from the context (there is a
> standard JAX-WS property for that) and use the session directly.  You can
> grab the current message from PhaseInterceptorChain.getCurrentMessage and
> grab the exchange and the session from that.   Etc.....

One note about this that probably should be mentioned:   right now, only the 
HTTP transports support any type of session.  Thus, technically, using the 
HTTPServletRequest is fine.

HOWEVER, the Session was stuck on the Exchange LONG LONG ago and wrappered 
with our own API specifically so that at some point, we could implement the 
various WS-* specs that do sessiony things.   Just never really had a 
need/demand to add that though.   Thus, the sessions won't work with JMS and 
the other transports.   However, an interceptor could easily create a new 
Session backed by something and stick that on the exchange for use with this.


-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog

Re: Stateful web services with CXF

Posted by Daniel Kulp <dk...@apache.org>.
On Thursday 21 October 2010 5:17:29 pm thegreatone wrote:
> Thx for the help.
> 
> Is there any way to avoid copying the cookies from one proxy to another?

Probably not, which is one of the reasons stateful services are hightly 
discouraged. 

The normal behavior it to have the login return some sort of token that is 
then passed into all the other operations so they can remain stateless.   The 
operations use that token to figure out what data they need.



> I'm sure most clients can do it though I haven't tried with C# .net yet -
> that makes up the bulk of my web service clients.
-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog

Re: Stateful web services with CXF

Posted by thegreatone <lo...@hotmail.com>.
Thx for the help.

Is there any way to avoid copying the cookies from one proxy to another?

I'm sure most clients can do it though I haven't tried with C# .net yet -
that makes up the bulk of my web service clients.
-- 
View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3231393.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Stateful web services with CXF

Posted by Daniel Kulp <dk...@apache.org>.
On Tuesday 19 October 2010 5:51:15 pm thegreatone wrote:
> I have a few questions.
> 
> Regarding the code to publish BankImpl:
> 
>         Endpoint ep = Endpoint.publish("http://localhost:8080/BankAccount",
> new BankAccountImpl());
>         W3CEndpointReference er =
> (W3CEndpointReference)ep.getEndpointReference();
>         Endpoint.publish("http://localhost:8080/Bank", new BankImpl(er));
> 
> 
> I typically do things in Spring (for the server code at least).
> 
> I typically use <jaxws:endpoint>. I'm not 100% sure how to configure Spring
> to do what is shown above:
> 
> I would expect something like this:
> 
>    <jaxws:endpoint
>       id="bankEndpoint"
>       implementor="#bankImpl"
>       address="/Bank" />
> 
>    <bean id="bankImpl" class="com.dankulp.bank.BankImpl">
>       <constructor-arg ref="bankAccountEndpoint"/>
>    </bean>
> 
>    <jaxws:endpoint
>       id="bankAccountEndpoint"
>       implementor="#bankAccountImpl"
>       address="/BankAccount" />
> 
>    <bean id="bankAccountImpl" class="com.dankulp.bank.BankAccountImpl"/>

Hmm...     I think the bank account could just be:

<jaxws:endpoint
      id="bankAccountEndpoint"
    implementorClass="com.dankulp.bank.BankAccountImpl"
      address="/BankAccount" />
which would avoid even creating a BankAccountImpl at startup.

For the other, passing that as a constructor arg is probably correct, but the 
constructor would change to:

Bank(Endpoint ep) {
   ref = ep.getEndpointReference();
}


-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog

Re: Stateful web services with CXF

Posted by thegreatone <lo...@hotmail.com>.
Thank you making the changes. 

I look forwards to seeing this in a future release.
-- 
View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3227581.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Stateful web services with CXF

Posted by thegreatone <lo...@hotmail.com>.
I have a few questions.

Regarding the code to publish BankImpl:

        Endpoint ep = Endpoint.publish("http://localhost:8080/BankAccount",
new BankAccountImpl());
        W3CEndpointReference er =
(W3CEndpointReference)ep.getEndpointReference();
        Endpoint.publish("http://localhost:8080/Bank", new BankImpl(er)); 


I typically do things in Spring (for the server code at least).

I typically use <jaxws:endpoint>. I'm not 100% sure how to configure Spring
to do what is shown above:

I would expect something like this:

   <jaxws:endpoint 
      id="bankEndpoint" 
      implementor="#bankImpl" 
      address="/Bank" />

   <bean id="bankImpl" class="com.dankulp.bank.BankImpl">      
      <constructor-arg ref="bankAccountEndpoint"/>
   </bean>

   <jaxws:endpoint 
      id="bankAccountEndpoint" 
      implementor="#bankAccountImpl" 
      address="/BankAccount" />

   <bean id="bankAccountImpl" class="com.dankulp.bank.BankAccountImpl"/>      


I probably messed it up :)






-- 
View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3227666.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Stateful web services with CXF

Posted by Daniel Kulp <dk...@apache.org>.

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
dkulp@apache.org
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());
    }
}

Re: Stateful web services with CXF

Posted by Benson Margulies <bi...@gmail.com>.
Gosh that page is stale. We've been JAX-WS 2.0 for a long time.

On Fri, Oct 15, 2010 at 9:19 PM, thegreatone <lo...@hotmail.com> 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:
>
>  MessageContext messageContext = wsContext.getMessageContext();
>  String stateKey =
> EndpointReferenceUtils.getCurrentEndpointReferenceId(messageContext);
>  stateData = stateMap.get(stateKey);
>
>
> --
> View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3214696.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>

Re: Stateful web services with CXF

Posted by thegreatone <lo...@hotmail.com>.
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:

  MessageContext messageContext = wsContext.getMessageContext();
  String stateKey =
EndpointReferenceUtils.getCurrentEndpointReferenceId(messageContext);
  stateData = stateMap.get(stateKey);
  

-- 
View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3214696.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Stateful web services with CXF

Posted by Benson Margulies <bi...@gmail.com>.
Oy. That looks like the WS-ADDRESSing stuff.

On Fri, Oct 15, 2010 at 6:14 PM, thegreatone <lo...@hotmail.com> wrote:
>
> That looks like an improvement - squeaky wheel gets a greasin
>
> So how do we programatically return a new instance of a stateful bean from
> within a WS method.
>
> So, for example, we have the classic "Bank" web service bean that has a
> "getAccount" WS method. The "getAccount" method returns a stateful
> "BankAccount" endpoint.
>
> So it might look something like this:
>
> BankAccount getAccount(accountId, password)
>
> Once the client has the BankAccount endpoint, they can do operations like
> deduct and add amounts to their account without having to pass an account ID
> around:
>
> myAccount = getAccount("333522444", "my_password");
>
> myAccount.addFunds(4000.34)
> myAccount.withdrawFunds(5000.50)
> balance = myAccount.getBalance();
>
> etc..
>
>
>
>
>
> --
> View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3214570.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>

Re: Stateful web services with CXF

Posted by thegreatone <lo...@hotmail.com>.
That looks like an improvement - squeaky wheel gets a greasin 

So how do we programatically return a new instance of a stateful bean from
within a WS method.

So, for example, we have the classic "Bank" web service bean that has a
"getAccount" WS method. The "getAccount" method returns a stateful
"BankAccount" endpoint.

So it might look something like this:

BankAccount getAccount(accountId, password)

Once the client has the BankAccount endpoint, they can do operations like
deduct and add amounts to their account without having to pass an account ID
around:

myAccount = getAccount("333522444", "my_password");

myAccount.addFunds(4000.34)
myAccount.withdrawFunds(5000.50)
balance = myAccount.getBalance();

etc..





-- 
View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3214570.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Stateful web services with CXF

Posted by Daniel Kulp <dk...@apache.org>.
OK.   I just committed a new @FactoryType annotation to trunk (will merge to 
2.3 if it flushes out a bit).

You can add:
@FactoryType(FactoryType.Type.Session)

to your impl bean and just have something like:

   <jaxws:endpoint address="http://localhost:8080/Stateful2"
       implementorClass="org.apache.cxf.systest.http.SessionAnnotationGreeterImpl"/>

in your spring config and it will now be a session thing.  There are a couple 
other options.  See the @FactoryType class.

http://svn.apache.org/repos/asf/cxf/trunk/api/src/main/java/org/apache/cxf/annotations/FactoryType.java

Tests are in:
systests/transports/src/test/java/org/apache/cxf/systest/http/ClientServerSessionTest.java

What do people think of something like that?

Dan


On Friday 15 October 2010 4:33:04 pm Daniel Kulp wrote:
> Never mind.   The HTTPSession thing doesn't even work any way.  I'm adding
> a system test for it and discovered it doesn't work as the Session factory
> asks for the object with a QName, but the HTTP session only allows
> strings.   Will fix it.
>
> Dan
> 
> On Friday 15 October 2010 3:10:24 pm Daniel Kulp wrote:
> > On Friday 15 October 2010 8:24:58 am Benson Margulies wrote:
> > > Dan,
> > > 
> > > I'm a bit puzzled here.
> > > 
> > > The SessionFactory gets the session from the Exchange.
> > 
> > Right.
> > 
> > > For an endpoint deployed by API, the only call I can find that
> > > establishes the session is in
> > > org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest
> > > (S er vletContext, HttpServletRequest, HttpServletResponse). That makes
> > > a new session every time.
> > 
> > It makes a new HTTPSession which wrappers the HttpServletRequest.   It
> > doesn't actually call into the HttpServletRequest.getSession call until
> > you actually try to query something out of it.
> > org.apache.cxf.transport.http.HTTPSession
> > 
> > > If I needed some concept of sessions persisting across multiple calls,
> > > what would I do?
> > 
> > Well, you can get the HTTPServletRequest from the context (there is a
> > standard JAX-WS property for that) and use the session directly.  You can
> > grab the current message from PhaseInterceptorChain.getCurrentMessage and
> > grab the exchange and the session from that.   Etc.....

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog

Re: Stateful web services with CXF

Posted by Benson Margulies <bi...@gmail.com>.
It turns out that I don't even want to try to use this, and my reasons
might be interesting to other readers of this thread.

It sounds very nice to say that you get an instance of the
implementation bean for each session as defined by the servlet spec.
However, that sweeps a host of problems under a host of rugs.

What cleans up? If the instance obtains something on the expensive
side, like a database connection, does it just wait around for gc?
Maybe if you are tied to the Spring session system there's some nice
lifecycle behavior, but if you just launch an Endpoint with the CXF
JaxWsServerFactoryBean, looks like you don't get much assistance.

I suspect that this has something to do with why Metro tangles this up
with WS-A, but I'm pretty ignorant of all that.

Re: Stateful web services with CXF

Posted by Benson Margulies <bi...@gmail.com>.
When I've done this, I just made it a frank part of the protocol. The
client makes a 'start session' call and receives in return some sort
of token, and then the client keeps passing that token back to the
other calls, and the SIB worries about some sort of hash table of them
and deciding when to clean them up.

Adding a lot of hidden moving parts and mechanism to hide this in a
cookie or an attribute or a URL or something seems dubious to me
unless you somehow need to wrap an immutable existing contract in
session-fu.

Re: Stateful web services with CXF

Posted by thegreatone <lo...@hotmail.com>.
I guess we can "simulate" sessions by having the client call a web service
method that returns a session ID cookie and then the client can resend that
session cookie (JSESSIONID?).

Hardly ideal because not all WS clients are capable of sending cookies.
-- 
View this message in context: http://cxf.547215.n5.nabble.com/Stateful-web-services-with-CXF-tp3212822p3214521.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Stateful web services with CXF

Posted by Daniel Kulp <dk...@apache.org>.
Never mind.   The HTTPSession thing doesn't even work any way.  I'm adding a 
system test for it and discovered it doesn't work as the Session factory asks 
for the object with a QName, but the HTTP session only allows strings.   Will 
fix it.

Dan


On Friday 15 October 2010 3:10:24 pm Daniel Kulp wrote:
> On Friday 15 October 2010 8:24:58 am Benson Margulies wrote:
> > Dan,
> > 
> > I'm a bit puzzled here.
> > 
> > The SessionFactory gets the session from the Exchange.
> 
> Right.
> 
> > For an endpoint deployed by API, the only call I can find that
> > establishes the session is in
> > org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(S
> > er vletContext, HttpServletRequest, HttpServletResponse). That makes a
> > new session every time.
> 
> It makes a new HTTPSession which wrappers the HttpServletRequest.   It
> doesn't actually call into the HttpServletRequest.getSession call until
> you actually try to query something out of it.
> org.apache.cxf.transport.http.HTTPSession
> 
> > If I needed some concept of sessions persisting across multiple calls,
> > what would I do?
> 
> Well, you can get the HTTPServletRequest from the context (there is a
> standard JAX-WS property for that) and use the session directly.  You can
> grab the current message from PhaseInterceptorChain.getCurrentMessage and
> grab the exchange and the session from that.   Etc.....

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog

Re: Stateful web services with CXF

Posted by Daniel Kulp <dk...@apache.org>.
On Friday 15 October 2010 8:24:58 am Benson Margulies wrote:
> Dan,
> 
> I'm a bit puzzled here.
> 
> The SessionFactory gets the session from the Exchange. 

Right.

 
> For an endpoint deployed by API, the only call I can find that
> establishes the session is in
> org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(Ser
> vletContext, HttpServletRequest, HttpServletResponse). That makes a new
> session every time.

It makes a new HTTPSession which wrappers the HttpServletRequest.   It doesn't 
actually call into the HttpServletRequest.getSession call until you actually 
try to query something out of it. 
org.apache.cxf.transport.http.HTTPSession

> If I needed some concept of sessions persisting across multiple calls,
> what would I do?

Well, you can get the HTTPServletRequest from the context (there is a standard 
JAX-WS property for that) and use the session directly.  You can grab the 
current message from PhaseInterceptorChain.getCurrentMessage and grab the 
exchange and the session from that.   Etc.....

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog

Re: Stateful web services with CXF

Posted by Benson Margulies <bi...@gmail.com>.
Dan,

I'm a bit puzzled here.

The SessionFactory gets the session from the Exchange.

For an endpoint deployed by API, the only call I can find that
establishes the session is in
org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(ServletContext,
HttpServletRequest, HttpServletResponse). That makes a new session
every time.

If I needed some concept of sessions persisting across multiple calls,
what would I do?

Re: Stateful web services with CXF

Posted by Daniel Kulp <dk...@apache.org>.
On Thursday 14 October 2010 5:01:38 pm thegreatone wrote:
> I was reading how to do stateful web services using Metro:
> 
> https://metro.dev.java.net/1.4/docs/statefulWebservice.html
> 
> It uses the @Stateful annotation and returns and endpoint to the user that
> maintains the state.
> 
> I don't see how this can be done with CXF, or at least it's not documented
> well.
> 
> In the application I'm writing the server portion will be CXF (running in
> JBoss).
> 
> The clients can be anything but the big one is .net (C# / VB).
> 
> If the stateful WS solution doesn't work with .net clients, it's useless to
> me. None of the WS clients will be written with CXF.



There are two options:

1) Use the spring scopes and aop-proxy - this is generally what I recommend 
for normal scoping things such as per-request and session scopes as Spring has 
them built in.  
<bean class="my.ServiceImpl" id="myBean" scope="session">
<aop:scoped-proxy/>
</bean>

<jaxws:endpoint implementor="#myBean".../>



2) The cxf jaxws:endpoint/server config things have an invoker config element 
that can be used to specify a custom invoker.   You can either subclass the 
JAXWSMethodInvoker that we use or provide a custom Factory to it's 
constructor.  You could use  our  SessiontFactory:

http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/invoker/


Dan











-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog