Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2011, Red Hat, Inc., and individual contributors
   * as indicated by the @author tags. See the copyright.txt file in the
   * distribution for a full listing of individual contributors.
   *
   * This is free software; you can redistribute it and/or modify it
   * under the terms of the GNU Lesser General Public License as
   * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
 package org.jboss.as.ejb3.timerservice;
 
 import java.util.Date;
 
 
 
 import static org.jboss.as.ejb3.EjbLogger.ROOT_LOGGER;
 import static org.jboss.as.ejb3.EjbMessages.MESSAGES;

Implementation of EJB3.1 javax.ejb.Timer

Author(s):
Carlo de Wolf
Version:
$Revision: $
 
 public class TimerImpl implements Timer {

    
Unique id for this timer instance
 
     protected final String id;

    
The timer state
 
     protected volatile TimerState timerState;

    
The javax.ejb.TimerService through which this timer was created
 
     protected final TimerServiceImpl timerService;

    
The org.jboss.as.ejb3.timerservice.spi.TimedObjectInvoker to which this timer corresponds
 
     protected final TimedObjectInvoker timedObjectInvoker;

    
The info which was passed while creating the timer.
 
     protected final Serializable info;

    
Indicates whether the timer is persistent
 
     protected final boolean persistent;

    
A javax.ejb.TimerHandle for this timer
 
     protected final TimerHandleImpl handle;

    
The initial (first) expiry date of this timer
 
     protected final Date initialExpiration;

    
The duration in milli sec. between timeouts
 
    protected final long intervalDuration;

    
If this is an entity bean then this is the primary key
    protected final Object primaryKey;

    
Next expiry date of this timer
    protected volatile Date nextExpiration;

    
The date of the previous run of this timer
    protected volatile Date previousRun;

    
Creates a TimerImpl

Parameters:
id The id of this timer
service The timer service through which this timer was created
initialExpiry The first expiry of this timer
intervalDuration The duration (in milli sec) between timeouts
info The info that will be passed on through the javax.ejb.Timer and will be available through the javax.ejb.Timer.getInfo() method
persistent True if this timer is persistent. False otherwise
    public TimerImpl(String idTimerServiceImpl serviceDate initialExpirylong intervalDurationSerializable info,
                     boolean persistentObject primaryKeyfinal TimerState timerState) {
        this(idserviceinitialExpiryintervalDurationinitialExpiryinfopersistentprimaryKeytimerState);
    }

    
Creates a TimerImpl

Parameters:
id The id of this timer
service The timer service through which this timer was created
initialExpiry The first expiry of this timer. Can be null
intervalDuration The duration (in milli sec) between timeouts
nextEpiry The next expiry of this timer
info The info that will be passed on through the javax.ejb.Timer and will be available through the javax.ejb.Timer.getInfo() method
persistent True if this timer is persistent. False otherwise
    public TimerImpl(String idTimerServiceImpl serviceDate initialExpirylong intervalDurationDate nextEpiry,
                     Serializable infoboolean persistentObject primaryKeyfinal TimerState timerState) {
        assert service != null : "service is null";
        assert id != null : "id is null";
        this. = id;
        this. = service;
        this. = service.getInvoker();
        this. = info;
        this. = persistent;
        this. = initialExpiry;
        this. = intervalDuration;
        this. = nextEpiry;
        this. = null;
        this. = primaryKey;
        // create a timer handle for this timer
        this. = new TimerHandleImpl(this.this..getTimedObjectId(), service);
        this. = timerState;
    }

    
Creates a TimerImpl out of a persisted timer

Parameters:
persistedTimer The persisted state of the timer
service The timer service to which this timer belongs
    public TimerImpl(TimerEntity persistedTimerTimerServiceImpl service) {
        this(persistedTimer.getId(), servicepersistedTimer.getInitialDate(), persistedTimer.getInterval(),
                persistedTimer.getNextDate(), persistedTimer.getInfo(), truepersistedTimer.getPrimaryKey(), persistedTimer.getTimerState());
        this. = persistedTimer.getPreviousRun();
    }

    
Returns the id of this timer

Returns:
    public String getId() {
        return this.;
    }

    
    @Override
    public boolean isCalendarTimer() throws IllegalStateExceptionEJBException {
        // first check whether this timer has expired or cancelled
        this.assertTimerState();
        return false;
    }

    
    @Override
    public void cancel() throws IllegalStateExceptionEJBException {
        // first check whether the timer has expired or has been cancelled
        this.assertTimerState();
        boolean startedInTx =  == .;
        if ( != .) {
            setTimerState(.);
        }
        if (.transactionActive() && !startedInTx) {
            final Transaction currentTx = this..getTransaction();
            this.registerTimerCancellationWithTx(currentTx);
        } else {
            // cancel any scheduled Future for this timer
            this.cancelTimeout();
        }
        // persist changes
        .persistTimer(thisfalse);
    }

    
    @Override
        // make sure it's in correct state
        this.assertTimerState();
        // for non-persistent timers throws an exception (mandated by EJB3 spec)
        if (this. == false) {
            throw .invalidTimerHandlersForPersistentTimers("EJB3.1 Spec 18.2.6");
        }
        return this.;
    }

    
This method returns the javax.ejb.TimerHandle corresponding to this TimerImpl. Unlike the getHandle() method, this method does not throw an java.lang.IllegalStateException or javax.ejb.NoSuchObjectLocalException or javax.ejb.EJBException, for non-persistent timers. Instead this method returns the javax.ejb.TimerHandle corresponding to that non-persistent timer (remember that TimerImpl creates javax.ejb.TimerHandle for both persistent and non-persistent timers)

Returns:
    public TimerHandle getTimerHandle() {
        return this.;
    }

    
    @Override
    public boolean isPersistent() throws IllegalStateExceptionEJBException {
        // make sure the call is allowed in the current timer state
        this.assertTimerState();
        return this.;
    }

    

See also:
getTimerInfo()
    @Override
        // make sure this call is allowed
        this.assertTimerState();
        return this.;
    }

    
This method is similar to getInfo(), except that this method does not check the timer state and hence does not throw either java.lang.IllegalStateException or javax.ejb.NoSuchObjectLocalException or javax.ejb.EJBException.

Returns:
    public Serializable getTimerInfo() {
        return this.;
    }

    
    @Override
    public Date getNextTimeout() throws IllegalStateExceptionEJBException {
        // first check the validity of the timer state
        this.assertTimerState();
        if (this. == null) {
            throw .noMoreTimeoutForTimer(this);
        }
        return this.;
    }

    
This method is similar to getNextTimeout(), except that this method does not check the timer state and hence does not throw either java.lang.IllegalStateException or javax.ejb.NoSuchObjectLocalException or javax.ejb.EJBException.

Returns:
    public Date getNextExpiration() {
        return this.;
    }

    
Sets the next timeout of this timer

Parameters:
next The next scheduled timeout of this timer
    public void setNextTimeout(Date next) {
        this. = next;
    }

    
    @Override
        this.assertTimerState();
        throw .invalidTimerNotCalendarBaseTimer(this);
    }

    
    @Override
    public long getTimeRemaining() throws IllegalStateExceptionEJBException {
        // TODO: Rethink this implementation
        // first check the validity of the timer state
        this.assertTimerState();
        if (this. == null) {
            throw .noMoreTimeoutForTimer(this);
        }
        long currentTimeInMillis = System.currentTimeMillis();
        long nextTimeoutInMillis = this..getTime();
        // if the next expiration is *not* in future and the repeat interval isn't
        // a positive number (i.e. no repeats) then there won't be any more timeouts.
        // So throw a NoMoreTimeoutsException.
        // NOTE: We check for intervalDuration and not just nextExpiration because,
        // it's a valid case where the nextExpiration is in past (maybe the server was
        // down when the timeout was expected)
        //      if (nextTimeoutInMillis < currentTimeInMillis && this.intervalDuration <= 0)
        //      {
        //         throw new NoMoreTimeoutsException("No more timeouts for timer " + this);
        //      }
        return nextTimeoutInMillis - currentTimeInMillis;
    }
    public boolean isAutoTimer() {
        return false;
    }

    
Cancels any scheduled timer task for this timer
    protected void cancelTimeout() {
        // delegate to the timerservice, so that it can cancel any scheduled Future
        // for this timer
        this..cancelTimeout(this);
    }

    
Returns the initial (first) timeout date of this timer

Returns:
    public Date getInitialExpiration() {
        return this.;
    }

    
Returns the interval (in milli seconds), between timeouts, of this timer.

Returns:
    public long getInterval() {
        return this.;
    }

    
Returns the timed object id to which this timer belongs

Returns:
    public String getTimedObjectId() {
        return this..getInvoker().getTimedObjectId();
    }

    
Returns the timer service through which this timer was created

Returns:
    public TimerServiceImpl getTimerService() {
        return this.;
    }

    
Returns true if this timer is active. Else returns false.

A timer is considered to be "active", if its TimerState is neither of the following:

And if the corresponding timer service is still up

Returns:
    public boolean isActive() {
        return .isStarted() && !isCanceled() && !isExpired();
    }

    
Returns true if this timer is in TimerState.CANCELED state. Else returns false.

Returns:
    public boolean isCanceled() {
        return  == .;
    }

    
Returns true if this timer is in TimerState.EXPIRED state. Else returns false

Returns:
    public boolean isExpired() {
        return  == .;
    }

    
Returns true if this timer is in TimerState.RETRY_TIMEOUT. Else returns false.

Returns:
    public boolean isInRetry() {
        return  == .;
    }

    
Returns the java.util.Date of the previous timeout of this timer

Returns:
    public Date getPreviousRun() {
        return this.;
    }

    
Sets the java.util.Date of the previous timeout of this timer

Parameters:
previousRun
    public void setPreviousRun(Date previousRun) {
        this. = previousRun;
    }

    
Returns the current state of this timer

Returns:
    public TimerState getState() {
        return this.;
    }

    
Asserts that the timer is not in any of the following states:

Throws:
javax.ejb.NoSuchObjectLocalException if the txtimer was canceled or has expired
    protected void assertTimerState() {
        if ( == .)
            throw .timerHasExpired();
        if ( == .)
            throw .timerWasCanceled();
        AllowedMethodsInformation.checkAllowed(.);
    }

    
Expire, and remove it from the timer service.
    public void expireTimer() {
        .debug("expireTimer: " + this);
        // remove from timerservice
        .persistTimer(thisfalse);
        // Cancel any scheduled timer task for this timer
        this.cancelTimeout();
    }

    
Sets the state of this timer

Parameters:
state The state of this timer
    public void setTimerState(TimerState state) {
        this. = state;
    }

    
Returns the current persistent state of this timer
    public TimerEntity getPersistentState() {
        if (!this.) {
            throw .failToPersistTimer(this);
        }
        //we always create a new copy of the persistent state
        return this.createPersistentState();
    }

    
Suspends any currently scheduled task for this timer

Note that, suspend does not cancel the javax.ejb.Timer. Instead, it just cancels the next scheduled timeout. So once the javax.ejb.Timer is restored (whenever that happens), the javax.ejb.Timer will continue to timeout at appropriate times.

    // TODO: Revisit this method, we probably don't need this any more.
    // In terms of implementation, this is just equivalent to cancelTimeout() method
    public void suspend() {
        // cancel any scheduled timer task (Future) for this timer
        this.cancelTimeout();
    }

    
Creates and schedules a org.jboss.as.ejb3.timerservice.task.TimerTask for the next timeout of this timer

Parameters:
newTimer true if this is a new timer being scheduled, and not a re-schedule due to a timeout
    public void scheduleTimeout(boolean newTimer) {
        // just delegate to timerservice, for it to do the actual scheduling
        this..scheduleTimeout(thisnewTimer);
    }

    
Creates and returns a new persistent state of this timer

Returns:
    protected TimerEntity createPersistentState() {
        return new TimerEntity(this);
    }

    
Returns the task which handles the timeouts of this TimerImpl

    protected TimerTask<?> getTimerTask() {
        return new TimerTask<TimerImpl>(this);
    }

    
A javax.ejb.Timer is equal to another javax.ejb.Timer if their javax.ejb.TimerHandles are equal
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (this. == null) {
            return false;
        }
        if (obj instanceof TimerImpl == false) {
            return false;
        }
        TimerImpl otherTimer = (TimerImplobj;
        return this..equals(otherTimer.getTimerHandle());
    }
    @Override
    public int hashCode() {
        return this..hashCode();
    }


    
A nice formatted string output for this timer
    @Override
    public String toString() {
        //TODO: Cache this
        StringBuilder sb = new StringBuilder();
        sb.append("[id=");
        sb.append(this.);
        sb.append(" ");
        sb.append("timedObjectId=");
        if (this. == null) {
            sb.append("null");
        } else {
            sb.append(this..getTimedObjectId());
        }
        sb.append(" ");
        sb.append("auto-timer?:");
        sb.append(this.isAutoTimer());
        sb.append(" ");
        sb.append("persistent?:");
        sb.append(this.);
        sb.append(" ");
        sb.append("timerService=");
        sb.append(this.);
        sb.append(" ");
        sb.append("initialExpiration=");
        sb.append(this.);
        sb.append(" ");
        sb.append("intervalDuration(in milli sec)=");
        sb.append(this.);
        sb.append(" ");
        sb.append("nextExpiration=");
        sb.append(this.);
        sb.append(" ");
        sb.append("timerState=");
        sb.append(this.);
        return sb.toString();
    }
    private void registerTimerCancellationWithTx(Transaction tx) {
        try {
        } catch (Exception e) {
            throw .failToRegisterWithTxTimerCancellation(e);
        }
    }
    private Serializable deserialize(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        try {
            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStreamWithTCCL(bais);
            return (Serializableois.readObject();
        } catch (IOException ioe) {
            throw .failToDeserializeInfoInTimer(ioe);
        } catch (ClassNotFoundException cnfe) {
            throw .failToDeserializeInfoInTimer(cnfe);
        }
    }

    
TimerImpl.ObjectInputStreamWithTCCL during resolveClass(java.io.ObjectStreamClass) first tries to resolve the class in the thread context classloader java.lang.Thread.getContextClassLoader(). If it cannot resolve in the current context loader, it passes on the control to java.io.ObjectInputStream to resolve the class
    private final class ObjectInputStreamWithTCCL extends ObjectInputStream {
        public ObjectInputStreamWithTCCL(InputStream inthrows IOException {
            super(in);
        }
        protected Class<?> resolveClass(ObjectStreamClass vthrows IOExceptionClassNotFoundException {
            String className = v.getName();
            Class<?> resolvedClass = null;
            .trace("Attempting to locate class [" + className + "]");
            try {
                resolvedClass = .getClassLoader().loadClass(className);
            } catch (ClassNotFoundException e) {
                resolvedClass = getClass().getClassLoader().loadClass(className);
            }
            return resolvedClass;
        }
    }
    private class TimerCancellationTransactionSynchronization implements Synchronization {

        
The timer being managed in the transaction
        private TimerImpl timer;
            if (timer == null) {
                throw .timerIsNull();
            }
            this. = timer;
        }
        @Override
        public void afterCompletion(int status) {
            if (status == .) {
                .debug("commit timer cancellation: " + this.);
                this..cancelTimeout();
            } else if (status == .) {
                .debug("rollback timer cancellation: " + this.);
                this..setTimerState(.);
            }
        }
        @Override
        public void beforeCompletion() {
        }
    }
    public Object getPrimaryKey() {
        return ;
    }
New to GrepCode? Check out our FAQ X