Andrei,
Thanks for the reply. I'll try to explain my use case completely.

I'm writing a custom CXF transport for XMPP. XMPP is different from HTTP,
as the XMPP client keeps a constant socket connection open to the server.
For this use case, the CXF client should open its connection to the XMPP
server when the client is created. It should not wait until the first
message is sent.

To open the XMPP connection immediately,  my custom conduit extends
"org.apache.cxf.transport.AbstractConduit" and overrides the "activate()"
method. The  implementation opens the connection to the XMPP server. A
username/password is required to connect to the server. This means that my
custom conduit needs a username/password and XMPP server address prior to
the activate() method being called on the AbstractConduit.

My first attempt at implementing this was to set the username/password on
my custom transport factory. Then when the getConduit method was called,
the custom transport factory creates a new conduit that has the same
username/password set on it. It worked. The drawback is that all my clients
have to use the same username/password and the same XMPP server. I didn't
find this flexible enough.

Now, I'm trying to set the username/password and XMPP server address on the
conduit via a feature on the client. I feel this approach provides more
flexibility.  The problem occurs when calling "client.getConduit()". The
problem is that client.getConduit() triggers the conduit's activate()
method to be called. This leaves me in a catch-22 situation. The activate()
method that I implemented needs the username/password and XMPP server
address. The only way for a feature to get conduit is to call
client.getConduit().  Please see the code snipet below from the feature I'm
trying to use:

    public void initialize(Client client, Bus bus) {
        Conduit con = client.getConduit(); // activate() gets called here,
which is too early


        if (con instanceof XMPPConduit) {
            XMPPConduit xmppConduit = (XMPPConduit)con;
            xmppConduit.setUsername(this.username);
            ...
        } else {
            LOGGER.severe("This feature only supports XMPP clients");
        }
    }



On Wed, Jan 30, 2013 at 12:22 PM, Andrei Shakirin <[email protected]>wrote:

> Hi Leon,
>
> > This design worked as planned for the destination. A problem occurred
> when
> > using the same approach for the conduit. I would add features to the
> client,
> > and the initialize(Client, Bus) of the feature is triggered. I then
> attempt to use
> > Client.getConduit() so I can set properties on the conduit.
>
> I did not get your use case completely. Conduit is not related with
> features your adding to client.
> Conduit and Destination are created using TransportFactory, as described
> in article. Do you register your own transport factory?
> Basically call Client.getConduit() invokes Conduit selector which
> retrieves correct transport factory (based on endpoint url) and ask
> transport factory for conduit (getConduit() method).
>
> > Unfortunately calling Client.getConduit() eventually calls activate() on
> my
> > conduit, which results in a null pointer exception.
>
> Conduit has prepare() and close() methods. What do you mean with
> activate()?
>
> For more information just look how CXF transports are implemented:
> org.apache.cxf.transport.jms, org.apache.cxf.transport.local.
> You can find additional info in my blog:
> http://ashakirin.blogspot.de/2012/02/custom-cxf-transport.html .
>
> Regards,
> Andrei.
>
> > -----Original Message-----
> > From: Leon Doud [mailto:[email protected]]
> > Sent: Dienstag, 29. Januar 2013 03:25
> > To: [email protected]
> > Subject: Adding features to a conduit for a custom transport
> >
> > I'm implementing a custom transport. I planned to support the transport
> by
> > using features to setup the destination and conduit prior to them being
> > activated. This is based on what I read from
> http://cxf.apache.org/custom-
> > cxf-transport.html
> >
> > This design worked as planned for the destination. A problem occurred
> when
> > using the same approach for the conduit. I would add features to the
> client,
> > and the initialize(Client, Bus) of the feature is triggered. I then
> attempt to use
> > Client.getConduit() so I can set properties on the conduit.
> > Unfortunately calling Client.getConduit() eventually calls activate() on
> my
> > conduit, which results in a null pointer exception.
> >
> > Here is the stack trace, and the feature is XMPPService (I'm trying to
> set the
> > username/password in this case)
> >     at
> > org.apache.cxf.transport.xmpp.messaging.XMPPConduit.activate(XMPPCon
> > duit.java:57)
> >     at
> > org.apache.cxf.transport.AbstractObservable.setMessageObserver(Abstract
> > Observable.java:48)
> >     at
> > org.apache.cxf.endpoint.AbstractConduitSelector.getSelectedConduit(Abstr
> > actConduitSelector.java:115)
> >     at
> > org.apache.cxf.endpoint.UpfrontConduitSelector.selectConduit(UpfrontCon
> > duitSelector.java:77)
> >     at org.apache.cxf.endpoint.ClientImpl.getConduit(ClientImpl.java:846)
> >     at
> > org.apache.cxf.transport.xmpp.messaging.XMPPService.initialize(XMPPServi
> > ce.java:153)
> >
> > It seems like I'm in a catch-22. I want to use features to setup the
> conduit
> > before it is activated, but trying to use Client.getConduit() activates
> the
> > conduit. Is there someway to use Client.getConduit() (from the
> > implementation of the feature) without activating the conduit? I would
> > prefer to use features to configure the client/conduit and not the
> transport
> > factory.
> >
> > Thanks in advance,
> > Leon
>

Reply via email to