Yuri, Can you open a JIRA issue for this and attach your implementations?
http://issues.jasig.org Thanks! Scott On Tue, Dec 21, 2010 at 5:08 PM, Yuri Negocio Negocio <[email protected]>wrote: > Hi guys, > > A few months ago I'm working on customizing the CAS for my organization, I > have had some difficulties related to lack of architectural control in data > integration, due to the use of various frameworks (JPA, Hibernate, JDBC). > One example is the current implementation of the ticket cleaning lock > strategy. > > Because of that, i'm trying to replace the JDBC-based implementations to > JPA. The first step was to implement a class that replaces > JdbcLockingStrategy called JpaLockingStrategy. > > The class is fully based on the implementation of JdbcLockingStrategy and > has been tested on version 3.4.4 of cas server. > > Cheers, > > Yuri Feitosa Negócio > > import java.sql.Timestamp; > import java.util.Calendar; > import java.util.List; > > import javax.persistence.EntityManagerFactory; > import javax.validation.constraints.NotNull; > > import org.apache.commons.logging.Log; > import org.apache.commons.logging.LogFactory; > import org.jasig.cas.ticket.registry.support.LockingStrategy; > import org.springframework.beans.factory.InitializingBean; > import org.springframework.orm.jpa.JpaTemplate; > import org.springframework.transaction.annotation.Transactional; > > > public class JpaLockingStrategy > implements LockingStrategy, InitializingBean { > > protected final Log logger = > LogFactory.getLog(JpaLockingStrategy.class); > > @NotNull > private JpaTemplate jpaTemplate; > > public JpaLockingStrategy(final EntityManagerFactory factory) { > this.jpaTemplate = new JpaTemplate(factory); > } > > /** Default lock timeout is 1 hour */ > public static final int DEFAULT_LOCK_TIMEOUT = 3600; > > /** Unique identifier that identifies the client using this lock > instance */ > @NotNull > private String uniqueId; > > /** > * Application identifier that identifies rows in the locking table, > * each one of which may be for a different application or usage within > * a single application. > */ > @NotNull > private String applicationId; > > /** Amount of time in seconds lock may be held */ > private int lockTimeout = DEFAULT_LOCK_TIMEOUT; > > /** > * @param id Identifier used to identify this instance in a row of > the > * lock table. Must be unique across all clients vying for > * locks for a given application ID. > */ > public void setUniqueId(final String id) { > this.uniqueId = id; > } > > /** > * @param id Application identifier that identifies a row in the lock > * table for which multiple clients vie to hold the lock. > */ > public void setApplicationId(final String id) { > this.applicationId = id; > } > > > /** > * @param seconds Maximum amount of time in seconds lock may be held. > */ > public void setLockTimeout(final int seconds) { > this.lockTimeout = seconds; > } > > /** > * @see org.jasig.cas.ticket.registry.support.LockingStrategy#acquire() > */ > @Transactional > public boolean acquire() { > boolean lockAcquired = false; > try { > > List<Lock> locks = this.jpaTemplate.find("SELECT l FROM Lock l > WHERE l.applicationId = ?1",this.applicationId); > > final Timestamp expDate = getExpirationDate(); > > if ((locks==null)||locks.isEmpty()) { > logger.info("New lock. {applicationId: " + > this.applicationId + ", uniqueId: " + this.uniqueId + ", timestamp: " + > expDate + " }"); > Lock newLock = new Lock(); > // No row exists for this applicationId so create it. > // Row is created with uniqueId of this instance > // which indicates the lock is initially held by this > instance. > newLock.setApplicationId(this.applicationId); > newLock.setExpirationDate(expDate); > this.jpaTemplate.persist(newLock); > return true; > } else { > Lock currentLock = locks.get(0); > lockAcquired = canAcquire(currentLock); > if (lockAcquired) { > logger.info("Lock acquired. {applicationId: " + > this.applicationId + ", uniqueId: " + this.uniqueId + ", timestamp: " + > expDate + " }"); > > // Update unique ID of row to indicate this instance > holds lock > currentLock.setUniqueId(this.uniqueId); > > this.jpaTemplate.merge(currentLock); > } > } > } finally { > > } > return lockAcquired; > } > > /** > * @see org.jasig.cas.ticket.registry.support.LockingStrategy#release() > */ > @Transactional > public void release() { > logger.info("Lock released. { applicationId: " + > this.applicationId + " }"); > Lock lock = this.jpaTemplate.find(Lock.class, this.applicationId); > lock.setUniqueId(null); > lock.setExpirationDate(null); > this.jpaTemplate.merge(lock); > } > > /** > * Determines whether this instance can acquire the lock. > * > * @param lockRow Row of lock data for this application ID. > * > * @return True if lock can be acquired, false otherwise. > */ > private boolean canAcquire(Lock lock) { > if (lock.getUniqueId() != null) { > final Calendar expCal = Calendar.getInstance(); > expCal.setTime(lock.getExpirationDate()); > return Calendar.getInstance().after(expCal); > } > return true; > } > > /** > * @return The expiration date for a lock acquired at the current > system > * time > */ > private Timestamp getExpirationDate() { > final Calendar cal = Calendar.getInstance(); > cal.add(Calendar.SECOND, this.lockTimeout); > return new Timestamp(cal.getTimeInMillis()); > } > > public void afterPropertiesSet() throws Exception { > //compatibility > } > } > > > > import java.util.Date; > > import javax.persistence.Column; > import javax.persistence.Entity; > import javax.persistence.Id; > import javax.persistence.Table; > import javax.persistence.Temporal; > import javax.persistence.TemporalType; > > @Entity > @Table(name="LOCKS") > public class Lock { > > /** Database column name that holds application identifier */ > @Id > @Column(name="application_id") > private String applicationId; > /** Database column name that holds unique identifier */ > @Column(name="unique_id") > private String uniqueId; > > /** Database column name that holds expiration date */ > @Temporal(TemporalType.TIMESTAMP) > @Column(name="expiration_date") > private Date expirationDate; > > public String getApplicationId() { > return applicationId; > } > public void setApplicationId(String applicationId) { > this.applicationId = applicationId; > } > public String getUniqueId() { > return uniqueId; > } > public void setUniqueId(String uniqueId) { > this.uniqueId = uniqueId; > } > public Date getExpirationDate() { > return expirationDate; > } > public void setExpirationDate(Date expirationDate) { > this.expirationDate = expirationDate; > } > > } > > > -- > You are currently subscribed to [email protected] as: > [email protected] > > To unsubscribe, change settings or access archives, see > http://www.ja-sig.org/wiki/display/JSG/cas-user > > -- You are currently subscribed to [email protected] as: [email protected] To unsubscribe, change settings or access archives, see http://www.ja-sig.org/wiki/display/JSG/cas-user
