Done. https://issues.jasig.org/browse/CAS-930
On Tue, Dec 21, 2010 at 11:38 PM, Scott Battaglia <[email protected] > wrote: > 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 > > -- 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
