Friday 20 July 2012

XMPP CHAT ROOM MECHANISM # PART-2

In last we have seen how to get list of all available rooms in server. This post is about how to use those information to chat in a room.

Once user get list of all room. He needs to choose one room out of it to chat with. User will send presence to existing room. Here there is a little bit change in presence stanza. User needs to add nick name for the room. All other user will see him as his nick name rather than username. e.g.
<presence from='{user-jid}/{resource}' to='{room-id}@conference.domain/{nick-name}'></presence>
Server will send presence to all the members of the room. As if any user joins room later, he will also be sent the presence. This way server informs all users of chat room about joining and leaving event of any user.
<presence to='{user-jid}/{resource}' from='{room-id}@conference.domain/{nick-name}'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item role='participant' affiliation='none'></item>
</x>
</presence>
Once user gets successfull presence. I have mentioned "successfully", as there are some conditions when user can not enter in a room. In that case server will return a error presence stanza. You can get more details about such stanze from here. If some user have already sent some message the room. User will get all those message as following format whenever he will join a room.
<message to='{user-jid}/{resource}' from='{room-id}@conference.domain' type='groupchat'>
<subject>us.country</subject>
<delay stamp='2012-07-18T18:02:24.328Z' from='{room-id}@conference.domain' xmlns='urn:xmpp:delay'></delay>
<x stamp='20120718T18:02:24' from='{room-id}@conference.domain' xmlns='jabber:x:delay'></x>
</message>
Once user joins a room. He can start sending message to the room. Here user must provide type attribute for presence stanza having value as "groupchat". Describe as following xml.
<message type='groupchat' from = '{user-jid}/{resource}' to ='{room-id}@conference.domain'>
<body>dfdf</body>
</message>
Whatever message is being sent to chat room. Room will send that message to all current users of the room.
<message to='{user-jid}/{resource}' from='{room-id}@conference.domain/{nick-name}' type='groupchat'>
<body>dfdf</body>
</message>
Now when user gets tired of chatting with bunch of people. He would like to leave the room. He needs to send unavailable presence stanza to room's jid, including nickname also. Here nick name is important because a room identifies user based on their nick name. So when you join a room. It will lock that nick name for you. If you are leaving it, you need to make server to unlock the nick name.
<presence from='{user-jid}/{resource}' to='{room-id}@conference.domain/{nick-name}' type='unavailable'></presence>
Server will send user's presence details to all user who have joined the room. The user, who will join the room after that, will not get details about that user. Here if you notice. Server has added a role related information to stanza. Same type of information have been added when user sends presence stanza for joining. This role defines what can this user do with this room. I will post more details about that afterwards.
<presence to='{user-jid}/{resource}' type='unavailable' from='{room-id}@conference.domain/{nick-name}'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item role='none' affiliation='none'></item>
</x>
</presence>
Let me know if you have any queries regarding this post.

References : http://xmpp.org/extensions/xep-0045.html/

Thursday 19 July 2012

XMPP Chat room mechanism # Part-1

XMPP protocol provides specification for multi-user chatting(MUC). It is about service provider to implement it. You need to enable MUC from server side. Provider would also give facility to create persistent chat rooms. In terms of XMPP, chat room is known as conference. User can also create a new conference from client program.

When user is loggin in, he needs to ask for available service on server side. User need to send following XML to server.

<iq type='get' from='{user-jid/resource}' to='domain' id='discoitem1'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>

Server will send back all available services. Services will be sent as XML items. Each item contains service name and service JID.

<iq to='{user-jid/resource}' id='discoitem1' from='domain' type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item name='User Search' jid='search.domain'></item>
<item name='Socks 5 Bytestreams Proxy' jid='proxy.domain'></item>
<item name='Public Chatrooms' jid='conference.domain'></item>
<item name='Publish-Subscribe service' jid='pubsub.domain'></item>
</query>
</iq>

Once user gets all available services. It needs to be confirm whether conference service is there or not. If it is available user can ask for available chat rooms. These are all persistent chat rooms on the server.

<iq from='{user-jid/resource}' id='discoRooms' to='conference.domain' type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>

Server will send back all back all available chat rooms in following XML format.

<iq to='{user-jid/resource}' id='discoRooms' from='conference.domain' type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item name='university' jid='room1@conference.domain'></item>
<item name='country' jid='room2@conference.domain'></item>
</query>
</iq>

Now user is ready to join any room, he wants. User just needs to send one presence to the server. I will include more details about the same topic in next post. Stay in touch

Thursday 12 July 2012

OpenFire Sub Group

XMPP has concept of chat rooms. A chat room is basically a conference room where users can discuss on some points. But Yahoo has provided room facility as social chatting rooms where any member can join the group and chat with other members. In this feature "nested chat rooms" are provided.

XMPP is not basically providing nested or child chat rooms. But twisting the logic little bit can make it possible with normal XMPP also.

Recall the concepts of domain name. Facebook has domain "facebook.com". Then they have started services of application. They bought sub domain. That became "apps.facebook.com".

Similarly in XMPP suppose you are creating chat room with name University. The JID will be something like "university@domain.com". Now you want different universities as sub chat room of this one. Just create sub University as "oxford.university@domain.com". The main logic that you need to take care is at the client side. You need to show this rooms in tree structure so that user will see it as sub chat room instead of independent chat room.

Creating chat rooms from admin panel is very easy. It is just a html form filling task. But for creating a chat room from client is real programming stuff. You can get information about it from this link. Remember in XMPP room has many types. If you want to keep the room alive forever. You will have to create persistent room. Other rooms will be removed as soon as the last occupant will leave the room.

Let me know if you have any queries regarding all this.



Friday 6 July 2012

J2ME Theme development

LWUIT would not be best option for desktop base application. But when you need some good UI in mobile application. The UI that can attract people directly. You must need LWUIT. I have recently completed one project with J2ME with LWUIT.

Here with attaching demo for what you can do with LWUIT.


As well sharing resource file for this theme. Make sure you use same version of LWUIT for editing theme and mobile library otherwise it won't work. click here the resource file for this theme.

Monday 2 July 2012

Hibernate Caching: Part II

In first part of Hibernate Caching, we discussed about overall caching mechanism, strategies, implementation & configurations. Now in part two, we will look into Query cache and Caching association.

In many applications we have certain data sets which are permanent (not changing frequently) in nature but still dynmic like currencies supported, languages supported, countries etc. In such cases, it is useful to cache the exact results of a query, rather than caching certain objects. These queries would return exactly the same data set each time it is called.

To do this, you need to set the hibernate.cache.use_query_cache property in the hibernate.cfg.xml file to true, as follows:

<property name="hibernate.cache.use_query_cache">true</property>

Then, you use the setCacheable() method as follows on any query you wish to cache:

public class CurrencyDAO {
   public List getCurrencies() {
      return SessionManager.currentSession().createQuery("from Currency as c order by c.name")
                           .setCacheable(true)
                           .list();
   }
}

To guarantee the non-staleness of cache results, Hibernate expires the query cache results whenever cached data is modified in the application. However, it cannot anticipate any changes made by other applications directly in the database. So you should not use any second-level caching (or configure a short expiration timeout for class- and collection-cache regions) if your data has to be up-to-date all the time.

Now think of associations in hibernate. Suppose we have a list of students enrolled for different courses. The following is the Hibernate mapping of the Student class:

<hibernate-mapping package="org.avid.hibernate.caching">
<class name="Student" table="tbl_student" dynamic-update="true">
<id name="id" type="long" unsaved-value="null" >
    <column name="student_id" not-null="true"/>
    <generator class="increment"/>
</id>
 
<property column="last_name" name="lastName" type="string"/>
<property column="first_name" name="firstName" type="string"/>

<set name="courses" table="tbl_course_enrollment" lazy="false">
     <key column="student_id"/>
     <many-to-many column="course_id" class="Course"/>
</set>
</class>
</hibernate-mapping>
 
In order to make Hibernate fetch courses when you read student, you can set lazy to true. In practice, deactivating lazy loading is not a good idea. It again depends on your requirement and your EXPERTISE. Let's write DAO for Student while lazy loading is set to false:

public class StudentDAO {
   public List getStudents() {
         return SessionManager.currentSession().createQuery("from Student").list();
   }
} 
 
If you test the code, it will take too much of time even to load 50 or so students. This is typical of the N+1 query problem. Each query on the Student table is followed by literally hundreds of queries on the Course table. Whenever Hibernate retrieves a Student from the cache, it reloads all the associated courses. Let's first activate read/write caching on the Student class as follows:

<hibernate-mapping package="org.avid.hibernate.caching">
   <class name="Student" table="tbl_student" dynamic-update="true">
       <cache usage="read-write"/>
       ... 
   </class>
</hibernate-mapping>
 
We can also activate caching on the Course class. Read-only caching should do here:

    <class name="Language" table="Course" dynamic-update="true">
        <cache usage="read-only"/> ... </class> 
    </hibernate-mapping>
 
Then, you will need to configure the cache rules by adding the following entries to the ehcache.xml file:

<cache name="org.avid.hibernate.caching.Student" eternal="false" 
        overflowToDisk="false" timeToIdleSeconds="300" timeToLiveSeconds="600" />

<cache name="org.avid.hibernate.caching.Course" maxElementsInMemory="100" 
        eternal="true" overflowToDisk="false" />
 
This is fine, but it doesn't solve the N+1 query problem: 50 or so extra queries will still be executed whenever you load a Student. This is a case where you need to activate caching on the Course association in the Course.hbm.xml mapping file, as follows:

<hibernate-mapping package="org.avid.hibernate.caching">
 <class name="Student" table="tbl_student" dynamic-update="true">
   <id name="id" type="long" unsaved-value="null" > 
       <column name="student_id" not-null="true"/> 
       <generator class="increment"/> 
   </id> 

   <property column="last_name" name="lastName" type="string"/>
   <property column="emp_firstname" name="firstname" type="string"/> 


   <set name="courses" table="tbl_course_enrollment" lazy="false">
       <cache usage="read-write"/> 
       <key column="student_id"/>
       <many-to-many column="course_id" class="Course"/>
   </set> 
 </class> 
</hibernate-mapping> 

This configuration would get better or optimal performance.

Finally caching is a powerful technique, and Hibernate provides a powerful, flexible, and unobtrusive way of implementing it. Even the default configuration can provide substantial performance improvements in many simple cases.

However, like any powerful tool, Hibernate needs some thought and fine-tuning to obtain optimal results, and caching—like any other optimization technique—should be implemented using an incremental, test-driven approach. When done correctly, a small amount of well executed caching can boost your applications to their maximum capacities.
 

Sunday 1 July 2012

Hibernate Caching

Caching is widely used for optimizing database applications. A cache is designed to reduce traffic between your application and the database by conserving data already loaded from the database. Database access is necessary only when retrieving data that is not currently available in the cache. The application may need to empty (invalidate) the cache from time to time if the database is updated or modified in some way, because it has no way of knowing whether the cache is up to date.

When we use hibernate as persistence layer framework, we can cache objects using first level cache (associated with Session object) and second level cache (associated with SessionFactory object). The first level cache is used on transaction basis. Hibernate caches objects used in transaction as it may be read or updated multiple times. Whereas second level cache holds the object across multiple transactions. These objects are available to the whole application, not just to the user running the query. This way, each time a query returns an object that is already loaded in the cache, one or more database transactions potentially are avoided.

Also caching mechanism depends on your access strategies. There are four caching strategies:
  • Read-only: This strategy is useful for data that is read frequently but never updated. This is by far the simplest and best-performing cache strategy.
  • Read/write: Read/write caches may be appropriate if your data needs to be updated. They carry more overhead than read-only caches. In non-JTA environments, each transaction should be completed when Session.close() or Session.disconnect() is called.
  • Nonstrict read/write: This strategy does not guarantee that two transactions won't simultaneously modify the same data. Therefore, it may be most appropriate for data that is read often but only occasionally modified.
  • Transactional: This is a fully transactional cache that may be used only in a JTA environment.
 Hibernate supports the following open-source cache implementations out-of-the-box:
  • EHCache (org.hibernate.cache.EhCacheProvider)
  • OSCache (org.hibernate.cache.OSCacheProvider)
  • SwarmCache (org.hibernate.cache.SwarmCacheProvider)
  • JBoss TreeCache (org.hibernate.cache.TreeCacheProvider)

Cache
Read
only
Nonstrict Read/write
Read/write
Transactional
Clustering
Suitable for
EHCache
Yes
Yes
Yes
No
No
lightweight, and easy-to-use
OSCache
Yes
Yes
Yes
No
Basic (JavaGroups or JMS)
JSP pages or arbitrary objects
SwarmCache
Yes
Yes
No
No
Based on JavaGroups
many more read operations than write operations
JBoss TreeCache
Yes
No
No
Yes
Powerful
transaction-capable caching architecture

To activate second-level caching, you need to define the hibernate.cache.provider_class property in the hibernate.cfg.xml file as follows:

<hibernate-configuration>
<session-factory>
...
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EHCacheProvider
</property>
...
</session-factory>
</hibernate-configuration>
 
Second-level caching can be activated in one of the two following ways:
  1. On a class-by-class basis in the *.hbm.xml file, using the cache attribute:
    
    <hibernate-mapping package="com.avid.hibernate.caching">
    <class name="Currency" table="tbl_currency" dynamic-update="true">
    <meta attribute="implement-equals">true</meta>
    <cache usage="read-only"/>
    ...
    </class>
    </hibernate-mapping>
    
  2.  You can store all cache information in the hibernate.cfg.xml file, using the class-cache  attribute:
    
    <hibernate-configuration>
    <session-factory>
    ...
    <property name="hibernate.cache.provider_class">org.hibernate.cache.EHCacheProvider</property>
    ...
    <class-cache class="com.avid.hibernate.caching.Currency" usage="read-only" />
    </session-factory>
    </hibernate-configuration>
    
 
Next, you need to configure the cache rules for this class. Let's take an example of EHCache, but remember that each cache implementation is different. EHCache needs a configuration file (generally called ehcache.xml) at the classpath root.

<ehcache>
 <diskStore path="java.io.tmpdir"/>
 <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120"
      timeToLiveSeconds="120" overflowToDisk="true" diskPersistent="false"
      diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" />
 
  <cache name="com.avid.hibernate.caching.Currency" eternal="true" overflowToDisk="false" />
 </ehcache>

The beauty of hibernate lies in the declarative style. You do all these configurations and are ready to run. No need to change even a single line of code and performance is improved.