Java Mailing List Archive

http://www.junlu.com/

Home » Home (12/2007) » J2EE Pattern »

Re: Design question ...

Rafal Kedziorski

2003-07-15

Replies:

hi,

this is our implementation for lockKeywords:

    public synchronized boolean lockKeywords(Long caller_user_id, Integer mandant_id)
             throws CreateException {
        logger.debug("lockKeywords() entered");

        // get lock
        Long locked_user_id = isKeyworsLocked(mandant_id);

        // is allready locked
        if (caller_user_id.equals(locked_user_id)) {
            logger.warn("lockKeywords() keywords for mandant_id=" + mandant_id + " is allready locked");
            return true;
        }

        // keywords can't be locked more than one time
        if (locked_user_id != null) {
            logger.warn("lockKeywords() keywords for mandant_id=" + mandant_id + " is allready locked by other user_id=" + locked_user_id);
            return false;
        }

        // create lock
        keyword_historyLocalHome.create(caller_user_id, mandant_id, getKeyword_History_Type_Id(Keyword_History_TypeHelper.LOCKED), null);
        return true;
    }


    private Long isKeyworsLocked(Integer mandant_id) {
        // get id for LOCKED status
        Integer keyword_history_type_locked_id = getKeyword_History_Type_Id(Keyword_History_TypeHelper.LOCKED);

        try {
            // find all locks in history
            Iterator locked_keyword_historyIterator = keyword_historyLocalHome.findAllByMandantIdAndKeywordHistoryTypeId(mandant_id, keyword_history_type_locked_id).iterator();
            // get last lock
            Object object = null;
            while (locked_keyword_historyIterator.hasNext()) {
                object = locked_keyword_historyIterator.next();
            }

            // founded lock entry for given mandant?
            if (object != null) {
                // get id for UNLOCKED status
                Integer keyword_history_type_unlocked_id = getKeyword_History_Type_Id(Keyword_History_TypeHelper.UNLOCKED);

                Keyword_HistoryLocal locked_keyword_history = (Keyword_HistoryLocal) object;
                Long user_id = locked_keyword_history.getUsers_id();

                // find unlocks in history never than locked_keyword_history creation date
                Iterator unlocked_keyword_historyIterator = keyword_historyLocalHome.findAllByMandantIdAndKeywordHistoryTypeIdAndCreationDate(mandant_id, keyword_history_type_unlocked_id, locked_keyword_history.getCreation_date()).iterator();
                object = null;
                while (unlocked_keyword_historyIterator.hasNext()) {
                    object = unlocked_keyword_historyIterator.next();
                }

                // founded unlock entry for given user and keyword?

              // no -> is locked by user_id
                if (object == null) {
                    return user_id;
                }
                else {
                    Keyword_HistoryLocal unlocked_keyword_history = (Keyword_HistoryLocal) object;

                    Timestamp locked_creation_date = locked_keyword_history.getCreation_date();
                    Timestamp unlocked_creation_date = unlocked_keyword_history.getCreation_date();

                    // unlock after lock ?
                    if (unlocked_creation_date.after(locked_creation_date)) {
                        return null;
                    }

                    return user_id;
                }
            }
            else {
                return null;
            }
        }
        catch (FinderException fe) {
            logger.fatal("isKeyworsLocked() failed", fe);
            return null;
        }
    }

our client is communicating thru HTTP protocol with out JBoss server. you have to call lock keywords bevore you want edit keywords. after edit you have to unlock this module.

At 10:41 15.07.2003 -0400, you wrote:
Hi,
 
I might not understand your requirements properly.   However -
 
A:
 
If your lockKeywords method is simply trying to update the database entry to "locked" status, and returns either success or failure, it should still be capable of being made to work in a distributed environment.  You don't need to synchronize it, as your database resource manager should enforce consistency through its locking mechanism.  Provided you have your isolation level set to READ_COMMITTED or higher.
 
The downside of this is that the status is only available in the database, and you have to make a call to the database each time a user needs to lock a module.  If a large number of these requests are being made, and a reasonable proportion of them result in failure because the database is already locked, it might make sense to have your update preceded by a read.
 
You could always wrap this in a stateless session bean.  Naturally you require some means of reseting the database if a session locking the database crashes, or if a user fails to execute the unlock process. 
 
B:
 
The alternative is to go to some kind of distrbuted solution using RMI.  It is not that difficult to implement, in the basic case,unless your application has high availability requirements and you need to think about failover.   My feeling is that, unless your application usage patterns are unusual as compared to that of a typical content management solution, the RMI approach may not enhance performance enough to make it worth the work.  This would be especially true if you need to keep the lock status in the database.  On the other hand, if you can eliminate the requriement to use the database, it solves the reset issue.
 
C:
 
The singleton approach that Martin suggests could also work.  It is a practical means of distributing read only data that is centrally maintained (application configuration data, for instance).  To use it in this kind of situation with a database, you probably would want to have each Singleton attempt to update the database directly, rather than relying on the messaging backbone.  So the process would work like this.
 
1)  The client checks the singleton lock status for a particular module.
2)  If the module is not locked by another user, the singleton attempts to update the database (lock the module for the client).  If this fails, the client is informed the module is unavailable; if it suceeds, the client is allowed to begin editing.
3) If the lock attempt succeeds, some kind of process will be undertaken to notify the other singleton instances in the cluster that the indicated module is now locked.  This could be done by having the locking singleton issues a publish/subscribe msg via JMS.  Or you could have a central message producer activated by a trigger on the database. 
 
The main advantage of option C over A is that the probability of failure on the locking call is reduced.  This could be a significant issue if there is a lot of contention among users for certain modules.  Otherwise, it is probably not worth the effort, unless there are additional uses for the distributed singleton.

thanks. I will check, what is the best for us.


Regards,
Rafal

 
Cheers,  Jim W
 
 
-----Original Message----- "From: An interest list for Sun Java Center J2EE Pattern Catalog [mailto:J2EEPATTERNS-INTEREST@JAVA.SUN.COM]On Behalf Of Martin Zuzcak
Sent: July 15, 2003 7:31 AM
To: J2EEPATTERNS-INTEREST@JAVA.SUN.COM
Subject: Re: Design question ...


hi,
see singleton in cluster, you can resolve your problem similar way
http://www.javaspecialists.co.za/archive/Issue052.html

martin



Rafal Kedziorski <rafcio@POLONIUM.DE>
Odeslal: An interest list for Sun Java Center J2EE Pattern Catalog <J2EEPATTERNS-INTEREST@JAVA.SUN.COM>
13.07.2003 13:09
Odpovìzte prosím u¾ivateli An interest list for Sun Java Center J2EE Pattern Catalog
       
        Komu:        J2EEPATTERNS-INTEREST@JAVA.SUN.COM
        Kopie:       
        Pøedmìt:        Design question ...



hi,

I have a small design question for our problem which is working on a single
instance of an appicaltion server. we are working with JBoss 3.2.2.

Our application - multimedia content management system - is an modules
based application. You can store media files with partient mata data. You
can admin category trees and keywords. If some user want for example edit
categories or keywords, this module will be locked for this user for the
duration of the edit session. our lock is working on a singe instance
without problems. how we do this. we have this method:

public synchronized boolean lockKeywords(Long user_id, Integer mandant_id,
Long project_id)
  throws CreateException, ProjectException {
  ...
}

for each module we writes a history (created, changed, removed, locked,
unlocked, ...) to the db. this table we use for locking. we are searching
for the last unlock. id we found one, than the module can be locked for the
given user.

but this wan't works in an cluster environment. are the a pattern, which
can we use to solve our problem? or should we user other implementation?


Best Regards,
Rafal

====================================================================
Community Web Site (Core J2EE Patterns Catalog - Online Version):
http://java.sun.com/blueprints/corej2eepatterns
Getting Started (Beta Version):
http://developer.java.sun.com/developer/technicalArticles/J2EE/patterns/
Get the book:
http://www.amazon.com/exec/obidos/ASIN/0130648841/corej2eepatte-20
List Archive:
http://archives.java.sun.com/archives/j2eepatterns-interest.html
Unsubscribing:
email "signoff J2EEPATTERNS-INTEREST" to listserv@java.sun.com

©2008 junlu.com - Jax Systems, LLC, U.S.A.