As previously promised , I plan to start off writing a client.
The focus will be more on exposing the api exposed and (very) less of the UI.
So , either this code can be used directly to write a more fancy UI layer on top , or it can be used as a tutorial on how to understand and use the api.
Primary focus will be on the latter : hence code will be as clean and readable as possible with copious meaningful comments

(Normally , both of these would be false for my code

)
Where is the code going to be ? It will be
here at
dev.java.net - feel free to join the project !
I have just got the project approved and am a bit busy right now ... so the project is empty as of now - but expect action pretty soon !
The rate of progress would typically be not very fast and this blog will be in sync with it : as a new feature gets implemented , the related code and api would be discussed here.
Next entry : what are the dependencies of the api , how and where do we get them from , how to get and setup the api.
[Technorati Tag:
XMPP]
[Technorati Tag:
Sun IM api]
[Technorati Tag:
xmpp-im-client]
I was thinking up how to illustrate the various aspects of the
IM api ... and rather than write up posts about each facet with info
about them , my 'current' idea is this :
We will author a client - you and me together.
It wont be a fancy swing client : I am horrible at UI anyway

Instead of just writing dry posts with some code snippet , what I will
do is actually build a new text based client from scratch using the IM
api.
We will incrementally add functionality to it ... showcasing each aspect of it as we proceed.
It will not be exhaustive , obviously ... and you will be able to write
far more fancier and powerful clients than what I will end up authoring
here.
But the basic idea of how to use the IM api should be evident.
As I illustrated in the previous post , the client as such is going to
be agnostic to the underlying communication mechanism ... so you can
easily switch to using different session provider to use httpbind ,
tunnel through socks/https proxy , use legacy SSL mode , etc :
just a couple of line changes.
The rest of the client would remain the same.
Most probably , I will create a new project in dev.java.net with view-all permission.
So let the series begin from next post !
Let us consider a simple client which will use IM api and talk XMPP directly to the server.
The only modification to this client to use HTTP would be in the
session creation phase , so I will restrict the client to that part of
the code.
If you want to take a look at a more 'full fledged' client , take a look at
org.netbeans.lib.collab.tools.Shell.
CollaborationSessionFactory _factory = new CollaborationSessionFactory();
CollaborationSession _session = _factory.getSession(server , user, password, new CustomCollaborationSessionListener());
The behavior of this code is as follows :
- Lookup the system property
"org.netbeans.lib.collab.CollaborationSessionFactory" if specified ,
use that as the session provider factory , else.
- Fallback
onto the default CollaborationSessionFactory delegates to a direct
socket based XMPP stream :
org.netbeans.lib.collab.xmpp.XMPPSessionProvider.
The parameters are :
- Server url - this is an overloaded parameter. For a direct stream
based XMPP connection , this will be of the form "host:port". For our
HTTP case , it is slightly different - and I will detail it below.
- The user and password specified are used to authenticate the user. In a later post , I will write about how to use SASL.
- The
CollaborationSessionListener specified is the default listener to
dispatch events to. More interesting things can be done with
subinterfaces of CollaborationSessionListener - more on that too later

For a direct xmpp case , the above will look like this :
CollaborationSessionFactory _factory = new CollaborationSessionFactory();
CollaborationSession _session =
_factory.getSession("share.java.net:5222", "dummyuser",
"dummypassword", new CustomCollaborationSessionListener());
A bare bone CustomCollaborationSessionListener will just implement the
"public void onError(CollaborationException e);" without taking any
action about them.
public class CustomCollaborationSessionListener implements CollaborationSessionListener {
public void onError(CollaborationException e) { System.err.println("Collaboration exception : " + e); }
}
Thats it , your basic code will work now (the server specified above is
the netbeans collab server - create a valid userid and give the code
above a whirl !).
How to make this HTTP enabled ?
Just two changes :
- Specify the HTTP session provider class explicitly using :
- CollaborationSessionFactory _factory = new
CollaborationSessionFactory("com.sun.im.service.xmpp.httpbind.HTTPBindSessionProvider");
- Or
, set the env variable
"org.netbeans.lib.collab.CollaborationSessionFactory" to
"com.sun.im.service.xmpp.httpbind.HTTPBindSessionProvider" before creating the session factory.
- Change the server to point to a httpbind connection manager which
is JEP124 compliant. Additional parameters can be specified to this url
as query params : refer to HTTPBindConstants for list of actual parameters.
So , a JEP124 version of the initial code would be :
CollaborationSessionFactory _factory =
new
CollaborationSessionFactory("com.sun.im.service.xmpp.httpbind.HTTPBindSessionProvider");
CollaborationSession _session =
_factory.getSession("http://yourhost/httpgw/httpbind?to=acme.com&max_buffered_packets=100&max_buffered_bytes=100000",
"dummyuser",
"dummypassword", new CustomCollaborationSessionListener());
It is mandatory to specify the domain you want to talk to using the
'to' parameter. I am using two other parameters just to illustrate how
you would go about customising more.
The rest of the code which manipulates and uses the returned _session
is the same irrespective of whether it is direct XMPP or through HTTP.
Some caveats about the HTTP provider in collab codebase from the top of my head (ignore these if required) :
- It does not support proxies directly , but just relies on
URLConnection. So to use proxies , the user will need to explicitly set
the "http.proxyHost" and "http.proxyPort" system properties. (*More on
this below.)
- It does not honor the timeout's set as part of the initial handshake. (** More below).
* This limitation exists since the im module is also used from java 1.4
VM's. The ability to specify a per connection proxy was introduced
only in java 1.5 ...
How to fix this ?
It is very easy for a developer to write a custom
impl of
ConnectionProvider
to pick up the "proxytype" and "proxyhostport" param from the
service url and use it to connect to the httpbind gateway (If you want
to go with default impl itself , just extend it and override the
openConnection(URL) method).
** As part of the initial handshake with the gateway, the client and ht
tpbind gateway arrive at timeout's for the request.
These are not honored at the client side 'cos of the same limitation
above. Custom implementation can override and use the setReadTimeout()
and setConnectionTimeout() methods are appropriate.
If there is a need , I could always write a simple implementation of
ConnectionProvider for java 1.5 which gets over the above limitations.
What to expect next ?
What about how to use the basic client and start using TLS and SASL ?!
Yep , that should be fun - so watch out for next update soon !
In the recent IFR release of
Sun Java System Instant Messaging , we shipped our first implementation of
JEP 124 compliant client and gateway.
What does this provide ?
- Access to the Sun's XMPP server through HTTP.
- The IM client that we bundle with the product can now talk HTTP through any compliant connection manager to allow XMPP access.
The httpbind gateway (as we call it) is a servlet deployed in a
webcontainer which provides HTTP access to clients. You can consider it
as a protocol gateway between compliant HTTP
clients and our pure XMPP server - thats right , the server *does not*
know anything about http : everything is encapsulated and managed at
the gateway itself.
The default client that we ship is built on top of our IM client api which is hosted in netbeans under the
collab
project. The actual protocol is abstracted away at the api level and
the client
does not deal with XMPP (or whatever is the underlying protocol). The
api implementation which provides this client side access to XMPP
through HTTP is available opensource , give it a whirl ! (Any and every
help will be provided by me - drop me a note here

)
What all does this allow for :
- Obvious first case : use our client and our httpbind gateway and
talk over http through http proxies (not persistent CONNECT , but POST
requests
)
- Use a third party JEP 124 compliant client - either a AJAX client
like JWChat , or more heavier cousins and talk via HTTP to httpbind
enable XMPP access.
- Use the api and develop your own client - like what the collab
folks have done with the collab UI within netbeans : and how do you
make this HTTP enabled ? Just change the session provider - thats it
! (I know it works 'cos that is all I did to support this in our client
)
- Use constrained clients - like from a mobile phone , etc : talk
http and still be 'online' (subcase of 2 actually) ... internally for
demo's , we do have a J2ME midlet which does just this.
Ofcourse , this was just one of the main feature additions to
IFR release - the most notable among them being server pooling for high
availability and enhanced security through starttls and sasl support
(finally 1.0 compliant !) among many others.
Next blog entry , I will try to give a rough idea about how to go about
using this new code - some snippets are being promised

You will see
how simple it really is to dish out your own client , all the protocol
heavylifting is already handled at the api level - so let loose your UI
skills !
[Technorati Tag:
XMPP]
[Technorati Tag:
Sun IM api]
[Technorati Tag:
xmpp-im-client]