org.springframework.util.ErrorHandler

Here are the examples of the java api org.springframework.util.ErrorHandler taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

56 Examples 7

19 View Source File : JmsNamespaceHandlerTests.java
License : MIT License
Project Creator : Vip-Augus

@Test
public void testErrorHandlers() {
    ErrorHandler expected = this.context.getBean("testErrorHandler", ErrorHandler.clreplaced);
    ErrorHandler errorHandler1 = getErrorHandler("listener1");
    ErrorHandler errorHandler2 = getErrorHandler("listener2");
    ErrorHandler defaultErrorHandler = getErrorHandler(DefaultMessageListenerContainer.clreplaced.getName() + "#0");
    replacedertSame(expected, errorHandler1);
    replacedertSame(expected, errorHandler2);
    replacedertNull(defaultErrorHandler);
}

19 View Source File : AbstractMessageListenerContainer.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Abstract base clreplaced for Spring message listener container implementations.
 * Can either host a standard JMS {@link javax.jms.MessageListener} or Spring's
 * {@link SessionAwareMessageListener} for actual message processing.
 *
 * <p>Usually holds a single JMS {@link Connection} that all listeners are supposed
 * to be registered on, which is the standard JMS way of managing listener sessions.
 * Can alternatively also be used with a fresh Connection per listener, for Java EE
 * style XA-aware JMS messaging. The actual registration process is up to concrete
 * subclreplacedes.
 *
 * <p><b>NOTE:</b> The default behavior of this message listener container is to
 * <b>never</b> propagate an exception thrown by a message listener up to the JMS
 * provider. Instead, it will log any such exception at the error level.
 * This means that from the perspective of the attendant JMS provider no such
 * listener will ever fail. However, if error handling is necessary, then
 * any implementation of the {@link ErrorHandler} strategy may be provided to
 * the {@link #setErrorHandler(ErrorHandler)} method. Note that JMSExceptions
 * <b>will</b> be preplaceded to the ErrorHandler in addition to (but after) being
 * preplaceded to an {@link ExceptionListener}, if one has been provided.
 *
 * <p>The listener container offers the following message acknowledgment options:
 * <ul>
 * <li>"sessionAcknowledgeMode" set to "AUTO_ACKNOWLEDGE" (default):
 * This mode is container-dependent: For {@link DefaultMessageListenerContainer},
 * it means automatic message acknowledgment <i>before</i> listener execution, with
 * no redelivery in case of an exception and no redelivery in case of other listener
 * execution interruptions either. For {@link SimpleMessageListenerContainer},
 * it means automatic message acknowledgment <i>after</i> listener execution, with
 * no redelivery in case of a user exception thrown but potential redelivery in case
 * of the JVM dying during listener execution. In order to consistently arrange for
 * redelivery with any container variant, consider "CLIENT_ACKNOWLEDGE" mode or -
 * preferably - setting "sessionTransacted" to "true" instead.
 * <li>"sessionAcknowledgeMode" set to "DUPS_OK_ACKNOWLEDGE":
 * <i>Lazy</i> message acknowledgment during ({@link DefaultMessageListenerContainer})
 * or shortly after ({@link SimpleMessageListenerContainer}) listener execution;
 * no redelivery in case of a user exception thrown but potential redelivery in case
 * of the JVM dying during listener execution. In order to consistently arrange for
 * redelivery with any container variant, consider "CLIENT_ACKNOWLEDGE" mode or -
 * preferably - setting "sessionTransacted" to "true" instead.
 * <li>"sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE":
 * Automatic message acknowledgment <i>after</i> successful listener execution;
 * best-effort redelivery in case of a user exception thrown as well as in case
 * of other listener execution interruptions (such as the JVM dying).
 * <li>"sessionTransacted" set to "true":
 * Transactional acknowledgment after successful listener execution;
 * <i>guaranteed redelivery</i> in case of a user exception thrown as well as
 * in case of other listener execution interruptions (such as the JVM dying).
 * </ul>
 *
 * <p>There are two solutions to the duplicate message processing problem:
 * <ul>
 * <li>Either add <i>duplicate message detection</i> to your listener, in the
 * form of a business enreplacedy existence check or a protocol table check. This
 * usually just needs to be done in case of the JMSRedelivered flag being
 * set on the incoming message (otherwise just process straightforwardly).
 * Note that with "sessionTransacted" set to "true", duplicate messages will
 * only appear in case of the JVM dying at the most unfortunate point possible
 * (i.e. after your business logic executed but before the JMS part got committed),
 * so duplicate message detection is just there to cover a corner case.
 * <li>Or wrap your <i>entire processing with an XA transaction</i>, covering the
 * reception of the JMS message as well as the execution of the business logic in
 * your message listener (including database operations etc). This is only
 * supported by {@link DefaultMessageListenerContainer}, through specifying
 * an external "transactionManager" (typically a
 * {@link org.springframework.transaction.jta.JtaTransactionManager}, with
 * a corresponding XA-aware JMS {@link javax.jms.ConnectionFactory} preplaceded in
 * as "connectionFactory").
 * </ul>
 * Note that XA transaction coordination adds significant runtime overhead,
 * so it might be feasible to avoid it unless absolutely necessary.
 *
 * <p><b>Recommendations:</b>
 * <ul>
 * <li>The general recommendation is to set "sessionTransacted" to "true",
 * typically in combination with local database transactions triggered by the
 * listener implementation, through Spring's standard transaction facilities.
 * This will work nicely in Tomcat or in a standalone environment, often
 * combined with custom duplicate message detection (if it is unacceptable
 * to ever process the same message twice).
 * <li>Alternatively, specify a
 * {@link org.springframework.transaction.jta.JtaTransactionManager} as
 * "transactionManager" for a fully XA-aware JMS provider - typically when
 * running on a Java EE server, but also for other environments with a JTA
 * transaction manager present. This will give full "exactly-once" guarantees
 * without custom duplicate message checks, at the price of additional
 * runtime processing overhead.
 * </ul>
 *
 * <p>Note that the "sessionTransacted" flag is strongly recommended over
 * {@link org.springframework.jms.connection.JmsTransactionManager}, provided
 * that transactions do not need to be managed externally. As a consequence,
 * set the transaction manager only if you are using JTA or if you need to
 * synchronize with custom external transaction arrangements.
 *
 * @author Juergen Hoeller
 * @author Stephane Nicoll
 * @since 2.0
 * @see #setMessageListener
 * @see javax.jms.MessageListener
 * @see SessionAwareMessageListener
 * @see #handleListenerException
 * @see DefaultMessageListenerContainer
 * @see SimpleMessageListenerContainer
 * @see org.springframework.jms.listener.endpoint.JmsMessageEndpointManager
 */
public abstract clreplaced AbstractMessageListenerContainer extends AbstractJmsListeningContainer implements MessageListenerContainer {

    @Nullable
    private volatile Object destination;

    @Nullable
    private volatile String messageSelector;

    @Nullable
    private volatile Object messageListener;

    private boolean subscriptionDurable = false;

    private boolean subscriptionShared = false;

    @Nullable
    private String subscriptionName;

    @Nullable
    private Boolean replyPubSubDomain;

    @Nullable
    private QosSettings replyQosSettings;

    private boolean pubSubNoLocal = false;

    @Nullable
    private MessageConverter messageConverter;

    @Nullable
    private ExceptionListener exceptionListener;

    @Nullable
    private ErrorHandler errorHandler;

    private boolean exposeListenerSession = true;

    private boolean acceptMessagesWhileStopping = false;

    /**
     * Specify concurrency limits.
     */
    public abstract void setConcurrency(String concurrency);

    /**
     * Set the destination to receive messages from.
     * <p>Alternatively, specify a "destinationName", to be dynamically
     * resolved via the {@link org.springframework.jms.support.destination.DestinationResolver}.
     * <p>Note: The destination may be replaced at runtime, with the listener
     * container picking up the new destination immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     * @see #setDestinationName(String)
     */
    public void setDestination(@Nullable Destination destination) {
        this.destination = destination;
        if (destination instanceof Topic && !(destination instanceof Queue)) {
            // Clearly a Topic: let's set the "pubSubDomain" flag accordingly.
            setPubSubDomain(true);
        }
    }

    /**
     * Return the destination to receive messages from. Will be {@code null}
     * if the configured destination is not an actual {@link Destination} type;
     * c.f. {@link #setDestinationName(String) when the destination is a String}.
     */
    @Nullable
    public Destination getDestination() {
        return (this.destination instanceof Destination ? (Destination) this.destination : null);
    }

    /**
     * Set the name of the destination to receive messages from.
     * <p>The specified name will be dynamically resolved via the configured
     * {@link #setDestinationResolver destination resolver}.
     * <p>Alternatively, specify a JMS {@link Destination} object as "destination".
     * <p>Note: The destination may be replaced at runtime, with the listener
     * container picking up the new destination immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     * @see #setDestination(javax.jms.Destination)
     */
    public void setDestinationName(@Nullable String destinationName) {
        this.destination = destinationName;
    }

    /**
     * Return the name of the destination to receive messages from.
     * Will be {@code null} if the configured destination is not a
     * {@link String} type; c.f. {@link #setDestination(Destination) when
     * it is an actual Destination}.
     */
    @Nullable
    public String getDestinationName() {
        return (this.destination instanceof String ? (String) this.destination : null);
    }

    /**
     * Return a descriptive String for this container's JMS destination
     * (never {@code null}).
     */
    protected String getDestinationDescription() {
        Object destination = this.destination;
        return (destination != null ? destination.toString() : "");
    }

    /**
     * Set the JMS message selector expression (or {@code null} if none).
     * Default is none.
     * <p>See the JMS specification for a detailed definition of selector expressions.
     * <p>Note: The message selector may be replaced at runtime, with the listener
     * container picking up the new selector value immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     */
    public void setMessageSelector(@Nullable String messageSelector) {
        this.messageSelector = messageSelector;
    }

    /**
     * Return the JMS message selector expression (or {@code null} if none).
     */
    @Nullable
    public String getMessageSelector() {
        return this.messageSelector;
    }

    /**
     * Set the message listener implementation to register.
     * This can be either a standard JMS {@link MessageListener} object
     * or a Spring {@link SessionAwareMessageListener} object.
     * <p>Note: The message listener may be replaced at runtime, with the listener
     * container picking up the new listener object immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     * @throws IllegalArgumentException if the supplied listener is not a
     * {@link MessageListener} or a {@link SessionAwareMessageListener}
     * @see javax.jms.MessageListener
     * @see SessionAwareMessageListener
     */
    public void setMessageListener(@Nullable Object messageListener) {
        checkMessageListener(messageListener);
        this.messageListener = messageListener;
        if (messageListener != null && this.subscriptionName == null) {
            this.subscriptionName = getDefaultSubscriptionName(messageListener);
        }
    }

    /**
     * Return the message listener object to register.
     */
    @Nullable
    public Object getMessageListener() {
        return this.messageListener;
    }

    /**
     * Check the given message listener, throwing an exception
     * if it does not correspond to a supported listener type.
     * <p>By default, only a standard JMS {@link MessageListener} object or a
     * Spring {@link SessionAwareMessageListener} object will be accepted.
     * @param messageListener the message listener object to check
     * @throws IllegalArgumentException if the supplied listener is not a
     * {@link MessageListener} or a {@link SessionAwareMessageListener}
     * @see javax.jms.MessageListener
     * @see SessionAwareMessageListener
     */
    protected void checkMessageListener(@Nullable Object messageListener) {
        if (messageListener != null && !(messageListener instanceof MessageListener || messageListener instanceof SessionAwareMessageListener)) {
            throw new IllegalArgumentException("Message listener needs to be of type [" + MessageListener.clreplaced.getName() + "] or [" + SessionAwareMessageListener.clreplaced.getName() + "]");
        }
    }

    /**
     * Determine the default subscription name for the given message listener.
     * @param messageListener the message listener object to check
     * @return the default subscription name
     * @see SubscriptionNameProvider
     */
    protected String getDefaultSubscriptionName(Object messageListener) {
        if (messageListener instanceof SubscriptionNameProvider) {
            return ((SubscriptionNameProvider) messageListener).getSubscriptionName();
        } else {
            return messageListener.getClreplaced().getName();
        }
    }

    /**
     * Set whether to make the subscription durable. The durable subscription name
     * to be used can be specified through the "subscriptionName" property.
     * <p>Default is "false". Set this to "true" to register a durable subscription,
     * typically in combination with a "subscriptionName" value (unless
     * your message listener clreplaced name is good enough as subscription name).
     * <p>Only makes sense when listening to a topic (pub-sub domain),
     * therefore this method switches the "pubSubDomain" flag as well.
     * @see #setSubscriptionName
     * @see #setPubSubDomain
     */
    public void setSubscriptionDurable(boolean subscriptionDurable) {
        this.subscriptionDurable = subscriptionDurable;
        if (subscriptionDurable) {
            setPubSubDomain(true);
        }
    }

    /**
     * Return whether to make the subscription durable.
     */
    public boolean isSubscriptionDurable() {
        return this.subscriptionDurable;
    }

    /**
     * Set whether to make the subscription shared. The shared subscription name
     * to be used can be specified through the "subscriptionName" property.
     * <p>Default is "false". Set this to "true" to register a shared subscription,
     * typically in combination with a "subscriptionName" value (unless
     * your message listener clreplaced name is good enough as subscription name).
     * Note that shared subscriptions may also be durable, so this flag can
     * (and often will) be combined with "subscriptionDurable" as well.
     * <p>Only makes sense when listening to a topic (pub-sub domain),
     * therefore this method switches the "pubSubDomain" flag as well.
     * <p><b>Requires a JMS 2.0 compatible message broker.</b>
     * @since 4.1
     * @see #setSubscriptionName
     * @see #setSubscriptionDurable
     * @see #setPubSubDomain
     */
    public void setSubscriptionShared(boolean subscriptionShared) {
        this.subscriptionShared = subscriptionShared;
        if (subscriptionShared) {
            setPubSubDomain(true);
        }
    }

    /**
     * Return whether to make the subscription shared.
     * @since 4.1
     */
    public boolean isSubscriptionShared() {
        return this.subscriptionShared;
    }

    /**
     * Set the name of a subscription to create. To be applied in case
     * of a topic (pub-sub domain) with a shared or durable subscription.
     * <p>The subscription name needs to be unique within this client's
     * JMS client id. Default is the clreplaced name of the specified message listener.
     * <p>Note: Only 1 concurrent consumer (which is the default of this
     * message listener container) is allowed for each subscription,
     * except for a shared subscription (which requires JMS 2.0).
     * @since 4.1
     * @see #setPubSubDomain
     * @see #setSubscriptionDurable
     * @see #setSubscriptionShared
     * @see #setClientId
     * @see #setMessageListener
     */
    public void setSubscriptionName(@Nullable String subscriptionName) {
        this.subscriptionName = subscriptionName;
    }

    /**
     * Return the name of a subscription to create, if any.
     * @since 4.1
     */
    @Nullable
    public String getSubscriptionName() {
        return this.subscriptionName;
    }

    /**
     * Set the name of a durable subscription to create. This method switches
     * to pub-sub domain mode and activates subscription durability as well.
     * <p>The durable subscription name needs to be unique within this client's
     * JMS client id. Default is the clreplaced name of the specified message listener.
     * <p>Note: Only 1 concurrent consumer (which is the default of this
     * message listener container) is allowed for each durable subscription,
     * except for a shared durable subscription (which requires JMS 2.0).
     * @see #setPubSubDomain
     * @see #setSubscriptionDurable
     * @see #setSubscriptionShared
     * @see #setClientId
     * @see #setMessageListener
     */
    public void setDurableSubscriptionName(@Nullable String durableSubscriptionName) {
        this.subscriptionName = durableSubscriptionName;
        this.subscriptionDurable = (durableSubscriptionName != null);
    }

    /**
     * Return the name of a durable subscription to create, if any.
     */
    @Nullable
    public String getDurableSubscriptionName() {
        return (this.subscriptionDurable ? this.subscriptionName : null);
    }

    /**
     * Set whether to inhibit the delivery of messages published by its own connection.
     * Default is "false".
     * @since 4.1
     * @see javax.jms.Session#createConsumer(javax.jms.Destination, String, boolean)
     */
    public void setPubSubNoLocal(boolean pubSubNoLocal) {
        this.pubSubNoLocal = pubSubNoLocal;
    }

    /**
     * Return whether to inhibit the delivery of messages published by its own connection.
     * @since 4.1
     */
    public boolean isPubSubNoLocal() {
        return this.pubSubNoLocal;
    }

    /**
     * Configure the reply destination type. By default, the configured {@code pubSubDomain}
     * value is used (see {@link #isPubSubDomain()}.
     * <p>This setting primarily indicates what type of destination to resolve if dynamic
     * destinations are enabled.
     * @param replyPubSubDomain "true" for the Publish/Subscribe domain ({@link Topic Topics}),
     * "false" for the Point-to-Point domain ({@link Queue Queues})
     * @since 4.2
     * @see #setDestinationResolver
     */
    public void setReplyPubSubDomain(boolean replyPubSubDomain) {
        this.replyPubSubDomain = replyPubSubDomain;
    }

    /**
     * Return whether the Publish/Subscribe domain ({@link javax.jms.Topic Topics}) is used
     * for replies. Otherwise, the Point-to-Point domain ({@link javax.jms.Queue Queues})
     * is used.
     * @since 4.2
     */
    @Override
    public boolean isReplyPubSubDomain() {
        if (this.replyPubSubDomain != null) {
            return this.replyPubSubDomain;
        } else {
            return isPubSubDomain();
        }
    }

    /**
     * Configure the {@link QosSettings} to use when sending a reply. Can be set to
     * {@code null} to indicate that the broker's defaults should be used.
     * @param replyQosSettings the QoS settings to use when sending a reply or {@code null}
     * to use the default vas.
     * @since 5.0
     */
    public void setReplyQosSettings(@Nullable QosSettings replyQosSettings) {
        this.replyQosSettings = replyQosSettings;
    }

    @Override
    @Nullable
    public QosSettings getReplyQosSettings() {
        return this.replyQosSettings;
    }

    /**
     * Set the {@link MessageConverter} strategy for converting JMS Messages.
     * @since 4.1
     */
    public void setMessageConverter(@Nullable MessageConverter messageConverter) {
        this.messageConverter = messageConverter;
    }

    @Override
    @Nullable
    public MessageConverter getMessageConverter() {
        return this.messageConverter;
    }

    /**
     * Set the JMS ExceptionListener to notify in case of a JMSException thrown
     * by the registered message listener or the invocation infrastructure.
     */
    public void setExceptionListener(@Nullable ExceptionListener exceptionListener) {
        this.exceptionListener = exceptionListener;
    }

    /**
     * Return the JMS ExceptionListener to notify in case of a JMSException thrown
     * by the registered message listener or the invocation infrastructure, if any.
     */
    @Nullable
    public ExceptionListener getExceptionListener() {
        return this.exceptionListener;
    }

    /**
     * Set the ErrorHandler to be invoked in case of any uncaught exceptions thrown
     * while processing a Message.
     * <p>By default, there will be <b>no</b> ErrorHandler so that error-level
     * logging is the only result.
     */
    public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Return the ErrorHandler to be invoked in case of any uncaught exceptions thrown
     * while processing a Message.
     * @since 4.1
     */
    @Nullable
    public ErrorHandler getErrorHandler() {
        return this.errorHandler;
    }

    /**
     * Set whether to expose the listener JMS Session to a registered
     * {@link SessionAwareMessageListener} as well as to
     * {@link org.springframework.jms.core.JmsTemplate} calls.
     * <p>Default is "true", reusing the listener's {@link Session}.
     * Turn this off to expose a fresh JMS Session fetched from the same
     * underlying JMS {@link Connection} instead, which might be necessary
     * on some JMS providers.
     * <p>Note that Sessions managed by an external transaction manager will
     * always get exposed to {@link org.springframework.jms.core.JmsTemplate}
     * calls. So in terms of JmsTemplate exposure, this setting only affects
     * locally transacted Sessions.
     * @see SessionAwareMessageListener
     */
    public void setExposeListenerSession(boolean exposeListenerSession) {
        this.exposeListenerSession = exposeListenerSession;
    }

    /**
     * Return whether to expose the listener JMS {@link Session} to a
     * registered {@link SessionAwareMessageListener}.
     */
    public boolean isExposeListenerSession() {
        return this.exposeListenerSession;
    }

    /**
     * Set whether to accept received messages while the listener container
     * in the process of stopping.
     * <p>Default is "false", rejecting such messages through aborting the
     * receive attempt. Switch this flag on to fully process such messages
     * even in the stopping phase, with the drawback that even newly sent
     * messages might still get processed (if coming in before all receive
     * timeouts have expired).
     * <p><b>NOTE:</b> Aborting receive attempts for such incoming messages
     * might lead to the provider's retry count decreasing for the affected
     * messages. If you have a high number of concurrent consumers, make sure
     * that the number of retries is higher than the number of consumers,
     * to be on the safe side for all potential stopping scenarios.
     */
    public void setAcceptMessagesWhileStopping(boolean acceptMessagesWhileStopping) {
        this.acceptMessagesWhileStopping = acceptMessagesWhileStopping;
    }

    /**
     * Return whether to accept received messages while the listener container
     * in the process of stopping.
     */
    public boolean isAcceptMessagesWhileStopping() {
        return this.acceptMessagesWhileStopping;
    }

    @Override
    protected void validateConfiguration() {
        if (this.destination == null) {
            throw new IllegalArgumentException("Property 'destination' or 'destinationName' is required");
        }
    }

    @Override
    public void setupMessageListener(Object messageListener) {
        setMessageListener(messageListener);
    }

    // -------------------------------------------------------------------------
    // Template methods for listener execution
    // -------------------------------------------------------------------------
    /**
     * Execute the specified listener,
     * committing or rolling back the transaction afterwards (if necessary).
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @see #invokeListener
     * @see #commitIfNecessary
     * @see #rollbackOnExceptionIfNecessary
     * @see #handleListenerException
     */
    protected void executeListener(Session session, Message message) {
        try {
            doExecuteListener(session, message);
        } catch (Throwable ex) {
            handleListenerException(ex);
        }
    }

    /**
     * Execute the specified listener,
     * committing or rolling back the transaction afterwards (if necessary).
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see #invokeListener
     * @see #commitIfNecessary
     * @see #rollbackOnExceptionIfNecessary
     * @see #convertJmsAccessException
     */
    protected void doExecuteListener(Session session, Message message) throws JMSException {
        if (!isAcceptMessagesWhileStopping() && !isRunning()) {
            if (logger.isWarnEnabled()) {
                logger.warn("Rejecting received message because of the listener container " + "having been stopped in the meantime: " + message);
            }
            rollbackIfNecessary(session);
            throw new MessageRejectedWhileStoppingException();
        }
        try {
            invokeListener(session, message);
        } catch (JMSException | RuntimeException | Error ex) {
            rollbackOnExceptionIfNecessary(session, ex);
            throw ex;
        }
        commitIfNecessary(session, message);
    }

    /**
     * Invoke the specified listener: either as standard JMS MessageListener
     * or (preferably) as Spring SessionAwareMessageListener.
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see #setMessageListener
     */
    @SuppressWarnings("rawtypes")
    protected void invokeListener(Session session, Message message) throws JMSException {
        Object listener = getMessageListener();
        if (listener instanceof SessionAwareMessageListener) {
            doInvokeListener((SessionAwareMessageListener) listener, session, message);
        } else if (listener instanceof MessageListener) {
            doInvokeListener((MessageListener) listener, message);
        } else if (listener != null) {
            throw new IllegalArgumentException("Only MessageListener and SessionAwareMessageListener supported: " + listener);
        } else {
            throw new IllegalStateException("No message listener specified - see property 'messageListener'");
        }
    }

    /**
     * Invoke the specified listener as Spring SessionAwareMessageListener,
     * exposing a new JMS Session (potentially with its own transaction)
     * to the listener if demanded.
     * @param listener the Spring SessionAwareMessageListener to invoke
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see SessionAwareMessageListener
     * @see #setExposeListenerSession
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected void doInvokeListener(SessionAwareMessageListener listener, Session session, Message message) throws JMSException {
        Connection conToClose = null;
        Session sessionToClose = null;
        try {
            Session sessionToUse = session;
            if (!isExposeListenerSession()) {
                // We need to expose a separate Session.
                conToClose = createConnection();
                sessionToClose = createSession(conToClose);
                sessionToUse = sessionToClose;
            }
            // Actually invoke the message listener...
            listener.onMessage(message, sessionToUse);
            // Clean up specially exposed Session, if any.
            if (sessionToUse != session) {
                if (sessionToUse.getTransacted() && isSessionLocallyTransacted(sessionToUse)) {
                    // Transacted session created by this container -> commit.
                    JmsUtils.commitIfNecessary(sessionToUse);
                }
            }
        } finally {
            JmsUtils.closeSession(sessionToClose);
            JmsUtils.closeConnection(conToClose);
        }
    }

    /**
     * Invoke the specified listener as standard JMS MessageListener.
     * <p>Default implementation performs a plain invocation of the
     * {@code onMessage} method.
     * @param listener the JMS MessageListener to invoke
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see javax.jms.MessageListener#onMessage
     */
    protected void doInvokeListener(MessageListener listener, Message message) throws JMSException {
        listener.onMessage(message);
    }

    /**
     * Perform a commit or message acknowledgement, as appropriate.
     * @param session the JMS Session to commit
     * @param message the Message to acknowledge
     * @throws javax.jms.JMSException in case of commit failure
     */
    protected void commitIfNecessary(Session session, @Nullable Message message) throws JMSException {
        // Commit session or acknowledge message.
        if (session.getTransacted()) {
            // Commit necessary - but avoid commit call within a JTA transaction.
            if (isSessionLocallyTransacted(session)) {
                // Transacted session created by this container -> commit.
                JmsUtils.commitIfNecessary(session);
            }
        } else if (message != null && isClientAcknowledge(session)) {
            message.acknowledge();
        }
    }

    /**
     * Perform a rollback, if appropriate.
     * @param session the JMS Session to rollback
     * @throws javax.jms.JMSException in case of a rollback error
     */
    protected void rollbackIfNecessary(Session session) throws JMSException {
        if (session.getTransacted()) {
            if (isSessionLocallyTransacted(session)) {
                // Transacted session created by this container -> rollback.
                JmsUtils.rollbackIfNecessary(session);
            }
        } else if (isClientAcknowledge(session)) {
            session.recover();
        }
    }

    /**
     * Perform a rollback, handling rollback exceptions properly.
     * @param session the JMS Session to rollback
     * @param ex the thrown application exception or error
     * @throws javax.jms.JMSException in case of a rollback error
     */
    protected void rollbackOnExceptionIfNecessary(Session session, Throwable ex) throws JMSException {
        try {
            if (session.getTransacted()) {
                if (isSessionLocallyTransacted(session)) {
                    // Transacted session created by this container -> rollback.
                    if (logger.isDebugEnabled()) {
                        logger.debug("Initiating transaction rollback on application exception", ex);
                    }
                    JmsUtils.rollbackIfNecessary(session);
                }
            } else if (isClientAcknowledge(session)) {
                session.recover();
            }
        } catch (IllegalStateException ex2) {
            logger.debug("Could not roll back because Session already closed", ex2);
        } catch (JMSException | RuntimeException | Error ex2) {
            logger.error("Application exception overridden by rollback error", ex);
            throw ex2;
        }
    }

    /**
     * Check whether the given Session is locally transacted, that is, whether
     * its transaction is managed by this listener container's Session handling
     * and not by an external transaction coordinator.
     * <p>Note: The Session's own transacted flag will already have been checked
     * before. This method is about finding out whether the Session's transaction
     * is local or externally coordinated.
     * @param session the Session to check
     * @return whether the given Session is locally transacted
     * @see #isSessionTransacted()
     * @see org.springframework.jms.connection.ConnectionFactoryUtils#isSessionTransactional
     */
    protected boolean isSessionLocallyTransacted(Session session) {
        return isSessionTransacted();
    }

    /**
     * Create a JMS MessageConsumer for the given Session and Destination.
     * <p>This implementation uses JMS 1.1 API.
     * @param session the JMS Session to create a MessageConsumer for
     * @param destination the JMS Destination to create a MessageConsumer for
     * @return the new JMS MessageConsumer
     * @throws javax.jms.JMSException if thrown by JMS API methods
     */
    protected MessageConsumer createConsumer(Session session, Destination destination) throws JMSException {
        if (isPubSubDomain() && destination instanceof Topic) {
            if (isSubscriptionShared()) {
                return (isSubscriptionDurable() ? session.createSharedDurableConsumer((Topic) destination, getSubscriptionName(), getMessageSelector()) : session.createSharedConsumer((Topic) destination, getSubscriptionName(), getMessageSelector()));
            } else if (isSubscriptionDurable()) {
                return session.createDurableSubscriber((Topic) destination, getSubscriptionName(), getMessageSelector(), isPubSubNoLocal());
            } else {
                // Only preplaced in the NoLocal flag in case of a Topic (pub-sub mode):
                // Some JMS providers, such as WebSphere MQ 6.0, throw IllegalStateException
                // in case of the NoLocal flag being specified for a Queue.
                return session.createConsumer(destination, getMessageSelector(), isPubSubNoLocal());
            }
        } else {
            return session.createConsumer(destination, getMessageSelector());
        }
    }

    /**
     * Handle the given exception that arose during listener execution.
     * <p>The default implementation logs the exception at warn level,
     * not propagating it to the JMS provider — replaceduming that all handling of
     * acknowledgement and/or transactions is done by this listener container.
     * This can be overridden in subclreplacedes.
     * @param ex the exception to handle
     */
    protected void handleListenerException(Throwable ex) {
        if (ex instanceof MessageRejectedWhileStoppingException) {
            // Internal exception - has been handled before.
            return;
        }
        if (ex instanceof JMSException) {
            invokeExceptionListener((JMSException) ex);
        }
        if (isActive()) {
            // Regular case: failed while active.
            // Invoke ErrorHandler if available.
            invokeErrorHandler(ex);
        } else {
            // Rare case: listener thread failed after container shutdown.
            // Log at debug level, to avoid spamming the shutdown log.
            logger.debug("Listener exception after container shutdown", ex);
        }
    }

    /**
     * Invoke the registered JMS ExceptionListener, if any.
     * @param ex the exception that arose during JMS processing
     * @see #setExceptionListener
     */
    protected void invokeExceptionListener(JMSException ex) {
        ExceptionListener exceptionListener = getExceptionListener();
        if (exceptionListener != null) {
            exceptionListener.onException(ex);
        }
    }

    /**
     * Invoke the registered ErrorHandler, if any. Log at warn level otherwise.
     * @param ex the uncaught error that arose during JMS processing.
     * @see #setErrorHandler
     */
    protected void invokeErrorHandler(Throwable ex) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            errorHandler.handleError(ex);
        } else {
            logger.warn("Execution of JMS message listener failed, and no ErrorHandler has been set.", ex);
        }
    }

    /**
     * Internal exception clreplaced that indicates a rejected message on shutdown.
     * Used to trigger a rollback for an external transaction manager in that case.
     */
    @SuppressWarnings("serial")
    private static clreplaced MessageRejectedWhileStoppingException extends RuntimeException {
    }
}

19 View Source File : AbstractMessageListenerContainer.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Set the ErrorHandler to be invoked in case of any uncaught exceptions thrown
 * while processing a Message.
 * <p>By default, there will be <b>no</b> ErrorHandler so that error-level
 * logging is the only result.
 */
public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

19 View Source File : AbstractMessageListenerContainer.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Invoke the registered ErrorHandler, if any. Log at warn level otherwise.
 * @param ex the uncaught error that arose during JMS processing.
 * @see #setErrorHandler
 */
protected void invokeErrorHandler(Throwable ex) {
    ErrorHandler errorHandler = getErrorHandler();
    if (errorHandler != null) {
        errorHandler.handleError(ex);
    } else {
        logger.warn("Execution of JMS message listener failed, and no ErrorHandler has been set.", ex);
    }
}

19 View Source File : AbstractJmsListenerContainerFactory.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Base {@link JmsListenerContainerFactory} for Spring's base container implementation.
 *
 * @author Stephane Nicoll
 * @since 4.1
 * @param <C> the container type
 * @see AbstractMessageListenerContainer
 */
public abstract clreplaced AbstractJmsListenerContainerFactory<C extends AbstractMessageListenerContainer> implements JmsListenerContainerFactory<C> {

    protected final Log logger = LogFactory.getLog(getClreplaced());

    @Nullable
    private ConnectionFactory connectionFactory;

    @Nullable
    private DestinationResolver destinationResolver;

    @Nullable
    private ErrorHandler errorHandler;

    @Nullable
    private MessageConverter messageConverter;

    @Nullable
    private Boolean sessionTransacted;

    @Nullable
    private Integer sessionAcknowledgeMode;

    @Nullable
    private Boolean pubSubDomain;

    @Nullable
    private Boolean replyPubSubDomain;

    @Nullable
    private QosSettings replyQosSettings;

    @Nullable
    private Boolean subscriptionDurable;

    @Nullable
    private Boolean subscriptionShared;

    @Nullable
    private String clientId;

    @Nullable
    private Integer phase;

    @Nullable
    private Boolean autoStartup;

    /**
     * @see AbstractMessageListenerContainer#setConnectionFactory(ConnectionFactory)
     */
    public void setConnectionFactory(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    /**
     * @see AbstractMessageListenerContainer#setDestinationResolver(DestinationResolver)
     */
    public void setDestinationResolver(DestinationResolver destinationResolver) {
        this.destinationResolver = destinationResolver;
    }

    /**
     * @see AbstractMessageListenerContainer#setErrorHandler(ErrorHandler)
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * @see AbstractMessageListenerContainer#setMessageConverter(MessageConverter)
     */
    public void setMessageConverter(MessageConverter messageConverter) {
        this.messageConverter = messageConverter;
    }

    /**
     * @see AbstractMessageListenerContainer#setSessionTransacted(boolean)
     */
    public void setSessionTransacted(Boolean sessionTransacted) {
        this.sessionTransacted = sessionTransacted;
    }

    /**
     * @see AbstractMessageListenerContainer#setSessionAcknowledgeMode(int)
     */
    public void setSessionAcknowledgeMode(Integer sessionAcknowledgeMode) {
        this.sessionAcknowledgeMode = sessionAcknowledgeMode;
    }

    /**
     * @see AbstractMessageListenerContainer#setPubSubDomain(boolean)
     */
    public void setPubSubDomain(Boolean pubSubDomain) {
        this.pubSubDomain = pubSubDomain;
    }

    /**
     * @see AbstractMessageListenerContainer#setReplyPubSubDomain(boolean)
     */
    public void setReplyPubSubDomain(Boolean replyPubSubDomain) {
        this.replyPubSubDomain = replyPubSubDomain;
    }

    /**
     * @see AbstractMessageListenerContainer#setReplyQosSettings(QosSettings)
     */
    public void setReplyQosSettings(QosSettings replyQosSettings) {
        this.replyQosSettings = replyQosSettings;
    }

    /**
     * @see AbstractMessageListenerContainer#setSubscriptionDurable(boolean)
     */
    public void setSubscriptionDurable(Boolean subscriptionDurable) {
        this.subscriptionDurable = subscriptionDurable;
    }

    /**
     * @see AbstractMessageListenerContainer#setSubscriptionShared(boolean)
     */
    public void setSubscriptionShared(Boolean subscriptionShared) {
        this.subscriptionShared = subscriptionShared;
    }

    /**
     * @see AbstractMessageListenerContainer#setClientId(String)
     */
    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    /**
     * @see AbstractMessageListenerContainer#setPhase(int)
     */
    public void setPhase(int phase) {
        this.phase = phase;
    }

    /**
     * @see AbstractMessageListenerContainer#setAutoStartup(boolean)
     */
    public void setAutoStartup(boolean autoStartup) {
        this.autoStartup = autoStartup;
    }

    @Override
    public C createListenerContainer(JmsListenerEndpoint endpoint) {
        C instance = createContainerInstance();
        if (this.connectionFactory != null) {
            instance.setConnectionFactory(this.connectionFactory);
        }
        if (this.destinationResolver != null) {
            instance.setDestinationResolver(this.destinationResolver);
        }
        if (this.errorHandler != null) {
            instance.setErrorHandler(this.errorHandler);
        }
        if (this.messageConverter != null) {
            instance.setMessageConverter(this.messageConverter);
        }
        if (this.sessionTransacted != null) {
            instance.setSessionTransacted(this.sessionTransacted);
        }
        if (this.sessionAcknowledgeMode != null) {
            instance.setSessionAcknowledgeMode(this.sessionAcknowledgeMode);
        }
        if (this.pubSubDomain != null) {
            instance.setPubSubDomain(this.pubSubDomain);
        }
        if (this.replyPubSubDomain != null) {
            instance.setReplyPubSubDomain(this.replyPubSubDomain);
        }
        if (this.replyQosSettings != null) {
            instance.setReplyQosSettings(this.replyQosSettings);
        }
        if (this.subscriptionDurable != null) {
            instance.setSubscriptionDurable(this.subscriptionDurable);
        }
        if (this.subscriptionShared != null) {
            instance.setSubscriptionShared(this.subscriptionShared);
        }
        if (this.clientId != null) {
            instance.setClientId(this.clientId);
        }
        if (this.phase != null) {
            instance.setPhase(this.phase);
        }
        if (this.autoStartup != null) {
            instance.setAutoStartup(this.autoStartup);
        }
        initializeContainer(instance);
        endpoint.setupListenerContainer(instance);
        return instance;
    }

    /**
     * Create an empty container instance.
     */
    protected abstract C createContainerInstance();

    /**
     * Further initialize the specified container.
     * <p>Subclreplacedes can inherit from this method to apply extra
     * configuration if necessary.
     */
    protected void initializeContainer(C instance) {
    }
}

19 View Source File : AbstractJmsListenerContainerFactory.java
License : MIT License
Project Creator : Vip-Augus

/**
 * @see AbstractMessageListenerContainer#setErrorHandler(ErrorHandler)
 */
public void setErrorHandler(ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

19 View Source File : TimerManagerTaskScheduler.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Implementation of Spring's {@link TaskScheduler} interface, wrapping
 * a CommonJ {@link commonj.timers.TimerManager}.
 *
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @since 3.0
 * @deprecated as of 5.1, in favor of EE 7's
 * {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
 */
@Deprecated
public clreplaced TimerManagerTaskScheduler extends TimerManagerAccessor implements TaskScheduler {

    @Nullable
    private volatile ErrorHandler errorHandler;

    /**
     * Provide an {@link ErrorHandler} strategy.
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    @Override
    @Nullable
    public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
        return new ReschedulingTimerListener(errorHandlingTask(task, true), trigger).schedule();
    }

    @Override
    public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
        TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, false));
        Timer timer = obtainTimerManager().schedule(futureTask, startTime);
        futureTask.setTimer(timer);
        return futureTask;
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
        TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
        Timer timer = obtainTimerManager().scheduleAtFixedRate(futureTask, startTime, period);
        futureTask.setTimer(timer);
        return futureTask;
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
        TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
        Timer timer = obtainTimerManager().scheduleAtFixedRate(futureTask, 0, period);
        futureTask.setTimer(timer);
        return futureTask;
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
        TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
        Timer timer = obtainTimerManager().schedule(futureTask, startTime, delay);
        futureTask.setTimer(timer);
        return futureTask;
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
        TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
        Timer timer = obtainTimerManager().schedule(futureTask, 0, delay);
        futureTask.setTimer(timer);
        return futureTask;
    }

    private Runnable errorHandlingTask(Runnable delegate, boolean isRepeatingTask) {
        return TaskUtils.decorateTaskWithErrorHandler(delegate, this.errorHandler, isRepeatingTask);
    }

    /**
     * ScheduledFuture adapter that wraps a CommonJ Timer.
     */
    private static clreplaced TimerScheduledFuture extends FutureTask<Object> implements TimerListener, ScheduledFuture<Object> {

        @Nullable
        protected transient Timer timer;

        protected transient boolean cancelled = false;

        public TimerScheduledFuture(Runnable runnable) {
            super(runnable, null);
        }

        public void setTimer(Timer timer) {
            this.timer = timer;
        }

        @Override
        public void timerExpired(Timer timer) {
            runAndReset();
        }

        @Override
        public boolean cancel(boolean mayInterruptIfRunning) {
            boolean result = super.cancel(mayInterruptIfRunning);
            if (this.timer != null) {
                this.timer.cancel();
            }
            this.cancelled = true;
            return result;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            replacedert.state(this.timer != null, "No Timer available");
            return unit.convert(this.timer.getScheduledExecutionTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }

        @Override
        public int compareTo(Delayed other) {
            if (this == other) {
                return 0;
            }
            long diff = getDelay(TimeUnit.MILLISECONDS) - other.getDelay(TimeUnit.MILLISECONDS);
            return (diff == 0 ? 0 : ((diff < 0) ? -1 : 1));
        }
    }

    /**
     * ScheduledFuture adapter for trigger-based rescheduling.
     */
    private clreplaced ReschedulingTimerListener extends TimerScheduledFuture {

        private final Trigger trigger;

        private final SimpleTriggerContext triggerContext = new SimpleTriggerContext();

        private volatile Date scheduledExecutionTime = new Date();

        public ReschedulingTimerListener(Runnable runnable, Trigger trigger) {
            super(runnable);
            this.trigger = trigger;
        }

        @Nullable
        public ScheduledFuture<?> schedule() {
            Date nextExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
            if (nextExecutionTime == null) {
                return null;
            }
            this.scheduledExecutionTime = nextExecutionTime;
            setTimer(obtainTimerManager().schedule(this, this.scheduledExecutionTime));
            return this;
        }

        @Override
        public void timerExpired(Timer timer) {
            Date actualExecutionTime = new Date();
            super.timerExpired(timer);
            Date completionTime = new Date();
            this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
            if (!this.cancelled) {
                schedule();
            }
        }
    }
}

19 View Source File : TimerManagerTaskScheduler.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Provide an {@link ErrorHandler} strategy.
 */
public void setErrorHandler(ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

19 View Source File : TaskUtils.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Utility methods for decorating tasks with error handling.
 *
 * <p><b>NOTE:</b> This clreplaced is intended for internal use by Spring's scheduler
 * implementations. It is only public so that it may be accessed from impl clreplacedes
 * within other packages. It is <i>not</i> intended for general use.
 *
 * @author Mark Fisher
 * @author Juergen Hoeller
 * @since 3.0
 */
public abstract clreplaced TaskUtils {

    /**
     * An ErrorHandler strategy that will log the Exception but perform
     * no further handling. This will suppress the error so that
     * subsequent executions of the task will not be prevented.
     */
    public static final ErrorHandler LOG_AND_SUPPRESS_ERROR_HANDLER = new LoggingErrorHandler();

    /**
     * An ErrorHandler strategy that will log at error level and then
     * re-throw the Exception. Note: this will typically prevent subsequent
     * execution of a scheduled task.
     */
    public static final ErrorHandler LOG_AND_PROPAGATE_ERROR_HANDLER = new PropagatingErrorHandler();

    /**
     * Decorate the task for error handling. If the provided {@link ErrorHandler}
     * is not {@code null}, it will be used. Otherwise, repeating tasks will have
     * errors suppressed by default whereas one-shot tasks will have errors
     * propagated by default since those errors may be expected through the
     * returned {@link Future}. In both cases, the errors will be logged.
     */
    public static DelegatingErrorHandlingRunnable decorateTaskWithErrorHandler(Runnable task, @Nullable ErrorHandler errorHandler, boolean isRepeatingTask) {
        if (task instanceof DelegatingErrorHandlingRunnable) {
            return (DelegatingErrorHandlingRunnable) task;
        }
        ErrorHandler eh = (errorHandler != null ? errorHandler : getDefaultErrorHandler(isRepeatingTask));
        return new DelegatingErrorHandlingRunnable(task, eh);
    }

    /**
     * Return the default {@link ErrorHandler} implementation based on the boolean
     * value indicating whether the task will be repeating or not. For repeating tasks
     * it will suppress errors, but for one-time tasks it will propagate. In both
     * cases, the error will be logged.
     */
    public static ErrorHandler getDefaultErrorHandler(boolean isRepeatingTask) {
        return (isRepeatingTask ? LOG_AND_SUPPRESS_ERROR_HANDLER : LOG_AND_PROPAGATE_ERROR_HANDLER);
    }

    /**
     * An {@link ErrorHandler} implementation that logs the Throwable at error
     * level. It does not perform any additional error handling. This can be
     * useful when suppression of errors is the intended behavior.
     */
    private static clreplaced LoggingErrorHandler implements ErrorHandler {

        private final Log logger = LogFactory.getLog(LoggingErrorHandler.clreplaced);

        @Override
        public void handleError(Throwable t) {
            if (logger.isErrorEnabled()) {
                logger.error("Unexpected error occurred in scheduled task.", t);
            }
        }
    }

    /**
     * An {@link ErrorHandler} implementation that logs the Throwable at error
     * level and then propagates it.
     */
    private static clreplaced PropagatingErrorHandler extends LoggingErrorHandler {

        @Override
        public void handleError(Throwable t) {
            super.handleError(t);
            ReflectionUtils.rethrowRuntimeException(t);
        }
    }
}

19 View Source File : TaskUtils.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Decorate the task for error handling. If the provided {@link ErrorHandler}
 * is not {@code null}, it will be used. Otherwise, repeating tasks will have
 * errors suppressed by default whereas one-shot tasks will have errors
 * propagated by default since those errors may be expected through the
 * returned {@link Future}. In both cases, the errors will be logged.
 */
public static DelegatingErrorHandlingRunnable decorateTaskWithErrorHandler(Runnable task, @Nullable ErrorHandler errorHandler, boolean isRepeatingTask) {
    if (task instanceof DelegatingErrorHandlingRunnable) {
        return (DelegatingErrorHandlingRunnable) task;
    }
    ErrorHandler eh = (errorHandler != null ? errorHandler : getDefaultErrorHandler(isRepeatingTask));
    return new DelegatingErrorHandlingRunnable(task, eh);
}

19 View Source File : DelegatingErrorHandlingRunnable.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Runnable wrapper that catches any exception or error thrown from its
 * delegate Runnable and allows an {@link ErrorHandler} to handle it.
 *
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @since 3.0
 */
public clreplaced DelegatingErrorHandlingRunnable implements Runnable {

    private final Runnable delegate;

    private final ErrorHandler errorHandler;

    /**
     * Create a new DelegatingErrorHandlingRunnable.
     * @param delegate the Runnable implementation to delegate to
     * @param errorHandler the ErrorHandler for handling any exceptions
     */
    public DelegatingErrorHandlingRunnable(Runnable delegate, ErrorHandler errorHandler) {
        replacedert.notNull(delegate, "Delegate must not be null");
        replacedert.notNull(errorHandler, "ErrorHandler must not be null");
        this.delegate = delegate;
        this.errorHandler = errorHandler;
    }

    @Override
    public void run() {
        try {
            this.delegate.run();
        } catch (UndeclaredThrowableException ex) {
            this.errorHandler.handleError(ex.getUndeclaredThrowable());
        } catch (Throwable ex) {
            this.errorHandler.handleError(ex);
        }
    }

    @Override
    public String toString() {
        return "DelegatingErrorHandlingRunnable for " + this.delegate;
    }
}

19 View Source File : ThreadPoolTaskScheduler.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Implementation of Spring's {@link TaskScheduler} interface, wrapping
 * a native {@link java.util.concurrent.ScheduledThreadPoolExecutor}.
 *
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @since 3.0
 * @see #setPoolSize
 * @see #setRemoveOnCancelPolicy
 * @see #setThreadFactory
 * @see #setErrorHandler
 */
@SuppressWarnings("serial")
public clreplaced ThreadPoolTaskScheduler extends ExecutorConfigurationSupport implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler {

    private volatile int poolSize = 1;

    private volatile boolean removeOnCancelPolicy = false;

    @Nullable
    private volatile ErrorHandler errorHandler;

    @Nullable
    private ScheduledExecutorService scheduledExecutor;

    // Underlying ScheduledFutureTask to user-level ListenableFuture handle, if any
    private final Map<Object, ListenableFuture<?>> listenableFutureMap = new ConcurrentReferenceHashMap<>(16, ConcurrentReferenceHashMap.ReferenceType.WEAK);

    /**
     * Set the ScheduledExecutorService's pool size.
     * Default is 1.
     * <p><b>This setting can be modified at runtime, for example through JMX.</b>
     */
    public void setPoolSize(int poolSize) {
        replacedert.isTrue(poolSize > 0, "'poolSize' must be 1 or higher");
        this.poolSize = poolSize;
        if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
            ((ScheduledThreadPoolExecutor) this.scheduledExecutor).setCorePoolSize(poolSize);
        }
    }

    /**
     * Set the remove-on-cancel mode on {@link ScheduledThreadPoolExecutor}.
     * <p>Default is {@code false}. If set to {@code true}, the target executor will be
     * switched into remove-on-cancel mode (if possible, with a soft fallback otherwise).
     * <p><b>This setting can be modified at runtime, for example through JMX.</b>
     */
    public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) {
        this.removeOnCancelPolicy = removeOnCancelPolicy;
        if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
            ((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(removeOnCancelPolicy);
        } else if (removeOnCancelPolicy && this.scheduledExecutor != null) {
            logger.debug("Could not apply remove-on-cancel policy - not a ScheduledThreadPoolExecutor");
        }
    }

    /**
     * Set a custom {@link ErrorHandler} strategy.
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    @Override
    protected ExecutorService initializeExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
        this.scheduledExecutor = createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler);
        if (this.removeOnCancelPolicy) {
            if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
                ((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(true);
            } else {
                logger.debug("Could not apply remove-on-cancel policy - not a ScheduledThreadPoolExecutor");
            }
        }
        return this.scheduledExecutor;
    }

    /**
     * Create a new {@link ScheduledExecutorService} instance.
     * <p>The default implementation creates a {@link ScheduledThreadPoolExecutor}.
     * Can be overridden in subclreplacedes to provide custom {@link ScheduledExecutorService} instances.
     * @param poolSize the specified pool size
     * @param threadFactory the ThreadFactory to use
     * @param rejectedExecutionHandler the RejectedExecutionHandler to use
     * @return a new ScheduledExecutorService instance
     * @see #afterPropertiesSet()
     * @see java.util.concurrent.ScheduledThreadPoolExecutor
     */
    protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
        return new ScheduledThreadPoolExecutor(poolSize, threadFactory, rejectedExecutionHandler);
    }

    /**
     * Return the underlying ScheduledExecutorService for native access.
     * @return the underlying ScheduledExecutorService (never {@code null})
     * @throws IllegalStateException if the ThreadPoolTaskScheduler hasn't been initialized yet
     */
    public ScheduledExecutorService getScheduledExecutor() throws IllegalStateException {
        replacedert.state(this.scheduledExecutor != null, "ThreadPoolTaskScheduler not initialized");
        return this.scheduledExecutor;
    }

    /**
     * Return the underlying ScheduledThreadPoolExecutor, if available.
     * @return the underlying ScheduledExecutorService (never {@code null})
     * @throws IllegalStateException if the ThreadPoolTaskScheduler hasn't been initialized yet
     * or if the underlying ScheduledExecutorService isn't a ScheduledThreadPoolExecutor
     * @see #getScheduledExecutor()
     */
    public ScheduledThreadPoolExecutor getScheduledThreadPoolExecutor() throws IllegalStateException {
        replacedert.state(this.scheduledExecutor instanceof ScheduledThreadPoolExecutor, "No ScheduledThreadPoolExecutor available");
        return (ScheduledThreadPoolExecutor) this.scheduledExecutor;
    }

    /**
     * Return the current pool size.
     * <p>Requires an underlying {@link ScheduledThreadPoolExecutor}.
     * @see #getScheduledThreadPoolExecutor()
     * @see java.util.concurrent.ScheduledThreadPoolExecutor#getPoolSize()
     */
    public int getPoolSize() {
        if (this.scheduledExecutor == null) {
            // Not initialized yet: replacedume initial pool size.
            return this.poolSize;
        }
        return getScheduledThreadPoolExecutor().getPoolSize();
    }

    /**
     * Return the current setting for the remove-on-cancel mode.
     * <p>Requires an underlying {@link ScheduledThreadPoolExecutor}.
     */
    public boolean isRemoveOnCancelPolicy() {
        if (this.scheduledExecutor == null) {
            // Not initialized yet: return our setting for the time being.
            return this.removeOnCancelPolicy;
        }
        return getScheduledThreadPoolExecutor().getRemoveOnCancelPolicy();
    }

    /**
     * Return the number of currently active threads.
     * <p>Requires an underlying {@link ScheduledThreadPoolExecutor}.
     * @see #getScheduledThreadPoolExecutor()
     * @see java.util.concurrent.ScheduledThreadPoolExecutor#getActiveCount()
     */
    public int getActiveCount() {
        if (this.scheduledExecutor == null) {
            // Not initialized yet: replacedume no active threads.
            return 0;
        }
        return getScheduledThreadPoolExecutor().getActiveCount();
    }

    // SchedulingTaskExecutor implementation
    @Override
    public void execute(Runnable task) {
        Executor executor = getScheduledExecutor();
        try {
            executor.execute(errorHandlingTask(task, false));
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public void execute(Runnable task, long startTimeout) {
        execute(task);
    }

    @Override
    public Future<?> submit(Runnable task) {
        ExecutorService executor = getScheduledExecutor();
        try {
            return executor.submit(errorHandlingTask(task, false));
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        ExecutorService executor = getScheduledExecutor();
        try {
            Callable<T> taskToUse = task;
            ErrorHandler errorHandler = this.errorHandler;
            if (errorHandler != null) {
                taskToUse = new DelegatingErrorHandlingCallable<>(task, errorHandler);
            }
            return executor.submit(taskToUse);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ListenableFuture<?> submitListenable(Runnable task) {
        ExecutorService executor = getScheduledExecutor();
        try {
            ListenableFutureTask<Object> listenableFuture = new ListenableFutureTask<>(task, null);
            executeAndTrack(executor, listenableFuture);
            return listenableFuture;
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
        ExecutorService executor = getScheduledExecutor();
        try {
            ListenableFutureTask<T> listenableFuture = new ListenableFutureTask<>(task);
            executeAndTrack(executor, listenableFuture);
            return listenableFuture;
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    private void executeAndTrack(ExecutorService executor, ListenableFutureTask<?> listenableFuture) {
        Future<?> scheduledFuture = executor.submit(errorHandlingTask(listenableFuture, false));
        this.listenableFutureMap.put(scheduledFuture, listenableFuture);
        listenableFuture.addCallback(result -> this.listenableFutureMap.remove(scheduledFuture), ex -> this.listenableFutureMap.remove(scheduledFuture));
    }

    @Override
    protected void cancelRemainingTask(Runnable task) {
        super.cancelRemainingTask(task);
        // Cancel replacedociated user-level ListenableFuture handle as well
        ListenableFuture<?> listenableFuture = this.listenableFutureMap.get(task);
        if (listenableFuture != null) {
            listenableFuture.cancel(true);
        }
    }

    // TaskScheduler implementation
    @Override
    @Nullable
    public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
        ScheduledExecutorService executor = getScheduledExecutor();
        try {
            ErrorHandler errorHandler = this.errorHandler;
            if (errorHandler == null) {
                errorHandler = TaskUtils.getDefaultErrorHandler(true);
            }
            return new ReschedulingRunnable(task, trigger, executor, errorHandler).schedule();
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
        ScheduledExecutorService executor = getScheduledExecutor();
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return executor.schedule(errorHandlingTask(task, false), initialDelay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
        ScheduledExecutorService executor = getScheduledExecutor();
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return executor.scheduleAtFixedRate(errorHandlingTask(task, true), initialDelay, period, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
        ScheduledExecutorService executor = getScheduledExecutor();
        try {
            return executor.scheduleAtFixedRate(errorHandlingTask(task, true), 0, period, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
        ScheduledExecutorService executor = getScheduledExecutor();
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), initialDelay, delay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
        ScheduledExecutorService executor = getScheduledExecutor();
        try {
            return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), 0, delay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    private Runnable errorHandlingTask(Runnable task, boolean isRepeatingTask) {
        return TaskUtils.decorateTaskWithErrorHandler(task, this.errorHandler, isRepeatingTask);
    }

    private static clreplaced DelegatingErrorHandlingCallable<V> implements Callable<V> {

        private final Callable<V> delegate;

        private final ErrorHandler errorHandler;

        public DelegatingErrorHandlingCallable(Callable<V> delegate, ErrorHandler errorHandler) {
            this.delegate = delegate;
            this.errorHandler = errorHandler;
        }

        @Override
        @Nullable
        public V call() throws Exception {
            try {
                return this.delegate.call();
            } catch (Throwable ex) {
                this.errorHandler.handleError(ex);
                return null;
            }
        }
    }
}

19 View Source File : ThreadPoolTaskScheduler.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Set a custom {@link ErrorHandler} strategy.
 */
public void setErrorHandler(ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

19 View Source File : ConcurrentTaskScheduler.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Adapter that takes a {@code java.util.concurrent.ScheduledExecutorService} and
 * exposes a Spring {@link org.springframework.scheduling.TaskScheduler} for it.
 * Extends {@link ConcurrentTaskExecutor} in order to implement the
 * {@link org.springframework.scheduling.SchedulingTaskExecutor} interface as well.
 *
 * <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
 * in order to use it for trigger-based scheduling if possible, instead of Spring's
 * local trigger management which ends up delegating to regular delay-based scheduling
 * against the {@code java.util.concurrent.ScheduledExecutorService} API. For JSR-236 style
 * lookup in a Java EE 7 environment, consider using {@link DefaultManagedTaskScheduler}.
 *
 * <p>Note that there is a pre-built {@link ThreadPoolTaskScheduler} that allows for
 * defining a {@link java.util.concurrent.ScheduledThreadPoolExecutor} in bean style,
 * exposing it as a Spring {@link org.springframework.scheduling.TaskScheduler} directly.
 * This is a convenient alternative to a raw ScheduledThreadPoolExecutor definition with
 * a separate definition of the present adapter clreplaced.
 *
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @since 3.0
 * @see java.util.concurrent.ScheduledExecutorService
 * @see java.util.concurrent.ScheduledThreadPoolExecutor
 * @see java.util.concurrent.Executors
 * @see DefaultManagedTaskScheduler
 * @see ThreadPoolTaskScheduler
 */
public clreplaced ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements TaskScheduler {

    @Nullable
    private static Clreplaced<?> managedScheduledExecutorServiceClreplaced;

    static {
        try {
            managedScheduledExecutorServiceClreplaced = ClreplacedUtils.forName("javax.enterprise.concurrent.ManagedScheduledExecutorService", ConcurrentTaskScheduler.clreplaced.getClreplacedLoader());
        } catch (ClreplacedNotFoundException ex) {
            // JSR-236 API not available...
            managedScheduledExecutorServiceClreplaced = null;
        }
    }

    private ScheduledExecutorService scheduledExecutor;

    private boolean enterpriseConcurrentScheduler = false;

    @Nullable
    private ErrorHandler errorHandler;

    /**
     * Create a new ConcurrentTaskScheduler,
     * using a single thread executor as default.
     * @see java.util.concurrent.Executors#newSingleThreadScheduledExecutor()
     */
    public ConcurrentTaskScheduler() {
        super();
        this.scheduledExecutor = initScheduledExecutor(null);
    }

    /**
     * Create a new ConcurrentTaskScheduler, using the given
     * {@link java.util.concurrent.ScheduledExecutorService} as shared delegate.
     * <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
     * in order to use it for trigger-based scheduling if possible,
     * instead of Spring's local trigger management.
     * @param scheduledExecutor the {@link java.util.concurrent.ScheduledExecutorService}
     * to delegate to for {@link org.springframework.scheduling.SchedulingTaskExecutor}
     * as well as {@link TaskScheduler} invocations
     */
    public ConcurrentTaskScheduler(ScheduledExecutorService scheduledExecutor) {
        super(scheduledExecutor);
        this.scheduledExecutor = initScheduledExecutor(scheduledExecutor);
    }

    /**
     * Create a new ConcurrentTaskScheduler, using the given {@link java.util.concurrent.Executor}
     * and {@link java.util.concurrent.ScheduledExecutorService} as delegates.
     * <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
     * in order to use it for trigger-based scheduling if possible,
     * instead of Spring's local trigger management.
     * @param concurrentExecutor the {@link java.util.concurrent.Executor} to delegate to
     * for {@link org.springframework.scheduling.SchedulingTaskExecutor} invocations
     * @param scheduledExecutor the {@link java.util.concurrent.ScheduledExecutorService}
     * to delegate to for {@link TaskScheduler} invocations
     */
    public ConcurrentTaskScheduler(Executor concurrentExecutor, ScheduledExecutorService scheduledExecutor) {
        super(concurrentExecutor);
        this.scheduledExecutor = initScheduledExecutor(scheduledExecutor);
    }

    private ScheduledExecutorService initScheduledExecutor(@Nullable ScheduledExecutorService scheduledExecutor) {
        if (scheduledExecutor != null) {
            this.scheduledExecutor = scheduledExecutor;
            this.enterpriseConcurrentScheduler = (managedScheduledExecutorServiceClreplaced != null && managedScheduledExecutorServiceClreplaced.isInstance(scheduledExecutor));
        } else {
            this.scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
            this.enterpriseConcurrentScheduler = false;
        }
        return this.scheduledExecutor;
    }

    /**
     * Specify the {@link java.util.concurrent.ScheduledExecutorService} to delegate to.
     * <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
     * in order to use it for trigger-based scheduling if possible,
     * instead of Spring's local trigger management.
     * <p>Note: This will only apply to {@link TaskScheduler} invocations.
     * If you want the given executor to apply to
     * {@link org.springframework.scheduling.SchedulingTaskExecutor} invocations
     * as well, preplaced the same executor reference to {@link #setConcurrentExecutor}.
     * @see #setConcurrentExecutor
     */
    public void setScheduledExecutor(@Nullable ScheduledExecutorService scheduledExecutor) {
        initScheduledExecutor(scheduledExecutor);
    }

    /**
     * Provide an {@link ErrorHandler} strategy.
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        replacedert.notNull(errorHandler, "ErrorHandler must not be null");
        this.errorHandler = errorHandler;
    }

    @Override
    @Nullable
    public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
        try {
            if (this.enterpriseConcurrentScheduler) {
                return new EnterpriseConcurrentTriggerScheduler().schedule(decorateTask(task, true), trigger);
            } else {
                ErrorHandler errorHandler = (this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
                return new ReschedulingRunnable(task, trigger, this.scheduledExecutor, errorHandler).schedule();
            }
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return this.scheduledExecutor.schedule(decorateTask(task, false), initialDelay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return this.scheduledExecutor.scheduleAtFixedRate(decorateTask(task, true), initialDelay, period, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
        try {
            return this.scheduledExecutor.scheduleAtFixedRate(decorateTask(task, true), 0, period, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return this.scheduledExecutor.scheduleWithFixedDelay(decorateTask(task, true), initialDelay, delay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
        try {
            return this.scheduledExecutor.scheduleWithFixedDelay(decorateTask(task, true), 0, delay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    private Runnable decorateTask(Runnable task, boolean isRepeatingTask) {
        Runnable result = TaskUtils.decorateTaskWithErrorHandler(task, this.errorHandler, isRepeatingTask);
        if (this.enterpriseConcurrentScheduler) {
            result = ManagedTaskBuilder.buildManagedTask(result, task.toString());
        }
        return result;
    }

    /**
     * Delegate that adapts a Spring Trigger to a JSR-236 Trigger.
     * Separated into an inner clreplaced in order to avoid a hard dependency on the JSR-236 API.
     */
    private clreplaced EnterpriseConcurrentTriggerScheduler {

        public ScheduledFuture<?> schedule(Runnable task, final Trigger trigger) {
            ManagedScheduledExecutorService executor = (ManagedScheduledExecutorService) scheduledExecutor;
            return executor.schedule(task, new javax.enterprise.concurrent.Trigger() {

                @Override
                @Nullable
                public Date getNextRunTime(@Nullable LastExecution le, Date taskScheduledTime) {
                    return (trigger.nextExecutionTime(le != null ? new SimpleTriggerContext(le.getScheduledStart(), le.getRunStart(), le.getRunEnd()) : new SimpleTriggerContext()));
                }

                @Override
                public boolean skipRun(LastExecution lastExecution, Date scheduledRunTime) {
                    return false;
                }
            });
        }
    }
}

19 View Source File : ConcurrentTaskScheduler.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Provide an {@link ErrorHandler} strategy.
 */
public void setErrorHandler(ErrorHandler errorHandler) {
    replacedert.notNull(errorHandler, "ErrorHandler must not be null");
    this.errorHandler = errorHandler;
}

19 View Source File : ConcurrentTaskScheduler.java
License : MIT License
Project Creator : Vip-Augus

@Override
@Nullable
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
    try {
        if (this.enterpriseConcurrentScheduler) {
            return new EnterpriseConcurrentTriggerScheduler().schedule(decorateTask(task, true), trigger);
        } else {
            ErrorHandler errorHandler = (this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
            return new ReschedulingRunnable(task, trigger, this.scheduledExecutor, errorHandler).schedule();
        }
    } catch (RejectedExecutionException ex) {
        throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
    }
}

19 View Source File : SimpleApplicationEventMulticaster.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Simple implementation of the {@link ApplicationEventMulticaster} interface.
 *
 * <p>Multicasts all events to all registered listeners, leaving it up to
 * the listeners to ignore events that they are not interested in.
 * Listeners will usually perform corresponding {@code instanceof}
 * checks on the preplaceded-in event object.
 *
 * <p>By default, all listeners are invoked in the calling thread.
 * This allows the danger of a rogue listener blocking the entire application,
 * but adds minimal overhead. Specify an alternative task executor to have
 * listeners executed in different threads, for example from a thread pool.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Stephane Nicoll
 * @see #setTaskExecutor
 */
public clreplaced SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

    @Nullable
    private Executor taskExecutor;

    @Nullable
    private ErrorHandler errorHandler;

    /**
     * Create a new SimpleApplicationEventMulticaster.
     */
    public SimpleApplicationEventMulticaster() {
    }

    /**
     * Create a new SimpleApplicationEventMulticaster for the given BeanFactory.
     */
    public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
        setBeanFactory(beanFactory);
    }

    /**
     * Set a custom executor (typically a {@link org.springframework.core.task.TaskExecutor})
     * to invoke each listener with.
     * <p>Default is equivalent to {@link org.springframework.core.task.SyncTaskExecutor},
     * executing all listeners synchronously in the calling thread.
     * <p>Consider specifying an asynchronous task executor here to not block the
     * caller until all listeners have been executed. However, note that asynchronous
     * execution will not participate in the caller's thread context (clreplaced loader,
     * transaction replacedociation) unless the TaskExecutor explicitly supports this.
     * @see org.springframework.core.task.SyncTaskExecutor
     * @see org.springframework.core.task.SimpleAsyncTaskExecutor
     */
    public void setTaskExecutor(@Nullable Executor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * Return the current task executor for this multicaster.
     */
    @Nullable
    protected Executor getTaskExecutor() {
        return this.taskExecutor;
    }

    /**
     * Set the {@link ErrorHandler} to invoke in case an exception is thrown
     * from a listener.
     * <p>Default is none, with a listener exception stopping the current
     * multicast and getting propagated to the publisher of the current event.
     * If a {@linkplain #setTaskExecutor task executor} is specified, each
     * individual listener exception will get propagated to the executor but
     * won't necessarily stop execution of other listeners.
     * <p>Consider setting an {@link ErrorHandler} implementation that catches
     * and logs exceptions (a la
     * {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_SUPPRESS_ERROR_HANDLER})
     * or an implementation that logs exceptions while nevertheless propagating them
     * (e.g. {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_PROPAGATE_ERROR_HANDLER}).
     * @since 4.1
     */
    public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Return the current error handler for this multicaster.
     * @since 4.1
     */
    @Nullable
    protected ErrorHandler getErrorHandler() {
        return this.errorHandler;
    }

    @Override
    public void multicastEvent(ApplicationEvent event) {
        multicastEvent(event, resolveDefaultEventType(event));
    }

    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        Executor executor = getTaskExecutor();
        // 遍历注册的消息监听器
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            } else {
                invokeListener(listener, event);
            }
        }
    }

    private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
        return ResolvableType.forInstance(event);
    }

    /**
     * Invoke the given listener with the given event.
     * @param listener the ApplicationListener to invoke
     * @param event the current event to propagate
     * @since 4.1
     */
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                doInvokeListener(listener, event);
            } catch (Throwable err) {
                errorHandler.handleError(err);
            }
        } else {
            doInvokeListener(listener, event);
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            listener.onApplicationEvent(event);
        } catch (ClreplacedCastException ex) {
            String msg = ex.getMessage();
            if (msg == null || matchesClreplacedCastMessage(msg, event.getClreplaced())) {
                // Possibly a lambda-defined listener which we could not resolve the generic event type for
                // -> let's suppress the exception and just log a debug message.
                Log logger = LogFactory.getLog(getClreplaced());
                if (logger.isTraceEnabled()) {
                    logger.trace("Non-matching event type for listener: " + listener, ex);
                }
            } else {
                throw ex;
            }
        }
    }

    private boolean matchesClreplacedCastMessage(String clreplacedCastMessage, Clreplaced<?> eventClreplaced) {
        // On Java 8, the message starts with the clreplaced name: "java.lang.String cannot be cast..."
        if (clreplacedCastMessage.startsWith(eventClreplaced.getName())) {
            return true;
        }
        // On Java 11, the message starts with "clreplaced ..." a.k.a. Clreplaced.toString()
        if (clreplacedCastMessage.startsWith(eventClreplaced.toString())) {
            return true;
        }
        // On Java 9, the message used to contain the module name: "java.base/java.lang.String cannot be cast..."
        int moduleSeparatorIndex = clreplacedCastMessage.indexOf('/');
        if (moduleSeparatorIndex != -1 && clreplacedCastMessage.startsWith(eventClreplaced.getName(), moduleSeparatorIndex + 1)) {
            return true;
        }
        // replaceduming an unrelated clreplaced cast failure...
        return false;
    }
}

19 View Source File : SimpleApplicationEventMulticaster.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Set the {@link ErrorHandler} to invoke in case an exception is thrown
 * from a listener.
 * <p>Default is none, with a listener exception stopping the current
 * multicast and getting propagated to the publisher of the current event.
 * If a {@linkplain #setTaskExecutor task executor} is specified, each
 * individual listener exception will get propagated to the executor but
 * won't necessarily stop execution of other listeners.
 * <p>Consider setting an {@link ErrorHandler} implementation that catches
 * and logs exceptions (a la
 * {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_SUPPRESS_ERROR_HANDLER})
 * or an implementation that logs exceptions while nevertheless propagating them
 * (e.g. {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_PROPAGATE_ERROR_HANDLER}).
 * @since 4.1
 */
public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

19 View Source File : JmsNamespaceHandlerTests.java
License : Apache License 2.0
Project Creator : SourceHot

@Test
public void testErrorHandlers() {
    ErrorHandler expected = this.context.getBean("testErrorHandler", ErrorHandler.clreplaced);
    ErrorHandler errorHandler1 = getErrorHandler("listener1");
    ErrorHandler errorHandler2 = getErrorHandler("listener2");
    ErrorHandler defaultErrorHandler = getErrorHandler(DefaultMessageListenerContainer.clreplaced.getName() + "#0");
    replacedertThat(errorHandler1).isSameAs(expected);
    replacedertThat(errorHandler2).isSameAs(expected);
    replacedertThat(defaultErrorHandler).isNull();
}

19 View Source File : AbstractMessageListenerContainer.java
License : Apache License 2.0
Project Creator : SourceHot

/**
 * Abstract base clreplaced for Spring message listener container implementations.
 * Can either host a standard JMS {@link javax.jms.MessageListener} or Spring's
 * {@link SessionAwareMessageListener} for actual message processing.
 *
 * <p>Usually holds a single JMS {@link Connection} that all listeners are supposed
 * to be registered on, which is the standard JMS way of managing listener sessions.
 * Can alternatively also be used with a fresh Connection per listener, for Java EE
 * style XA-aware JMS messaging. The actual registration process is up to concrete
 * subclreplacedes.
 *
 * <p><b>NOTE:</b> The default behavior of this message listener container is to
 * <b>never</b> propagate an exception thrown by a message listener up to the JMS
 * provider. Instead, it will log any such exception at the error level.
 * This means that from the perspective of the attendant JMS provider no such
 * listener will ever fail. However, if error handling is necessary, then
 * any implementation of the {@link ErrorHandler} strategy may be provided to
 * the {@link #setErrorHandler(ErrorHandler)} method. Note that JMSExceptions
 * <b>will</b> be preplaceded to the ErrorHandler in addition to (but after) being
 * preplaceded to an {@link ExceptionListener}, if one has been provided.
 *
 * <p>The listener container offers the following message acknowledgment options:
 * <ul>
 * <li>"sessionAcknowledgeMode" set to "AUTO_ACKNOWLEDGE" (default):
 * This mode is container-dependent: For {@link DefaultMessageListenerContainer},
 * it means automatic message acknowledgment <i>before</i> listener execution, with
 * no redelivery in case of an exception and no redelivery in case of other listener
 * execution interruptions either. For {@link SimpleMessageListenerContainer},
 * it means automatic message acknowledgment <i>after</i> listener execution, with
 * no redelivery in case of a user exception thrown but potential redelivery in case
 * of the JVM dying during listener execution. In order to consistently arrange for
 * redelivery with any container variant, consider "CLIENT_ACKNOWLEDGE" mode or -
 * preferably - setting "sessionTransacted" to "true" instead.
 * <li>"sessionAcknowledgeMode" set to "DUPS_OK_ACKNOWLEDGE":
 * <i>Lazy</i> message acknowledgment during ({@link DefaultMessageListenerContainer})
 * or shortly after ({@link SimpleMessageListenerContainer}) listener execution;
 * no redelivery in case of a user exception thrown but potential redelivery in case
 * of the JVM dying during listener execution. In order to consistently arrange for
 * redelivery with any container variant, consider "CLIENT_ACKNOWLEDGE" mode or -
 * preferably - setting "sessionTransacted" to "true" instead.
 * <li>"sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE":
 * Automatic message acknowledgment <i>after</i> successful listener execution;
 * best-effort redelivery in case of a user exception thrown as well as in case
 * of other listener execution interruptions (such as the JVM dying).
 * <li>"sessionTransacted" set to "true":
 * Transactional acknowledgment after successful listener execution;
 * <i>guaranteed redelivery</i> in case of a user exception thrown as well as
 * in case of other listener execution interruptions (such as the JVM dying).
 * </ul>
 *
 * <p>There are two solutions to the duplicate message processing problem:
 * <ul>
 * <li>Either add <i>duplicate message detection</i> to your listener, in the
 * form of a business enreplacedy existence check or a protocol table check. This
 * usually just needs to be done in case of the JMSRedelivered flag being
 * set on the incoming message (otherwise just process straightforwardly).
 * Note that with "sessionTransacted" set to "true", duplicate messages will
 * only appear in case of the JVM dying at the most unfortunate point possible
 * (i.e. after your business logic executed but before the JMS part got committed),
 * so duplicate message detection is just there to cover a corner case.
 * <li>Or wrap your <i>entire processing with an XA transaction</i>, covering the
 * reception of the JMS message as well as the execution of the business logic in
 * your message listener (including database operations etc). This is only
 * supported by {@link DefaultMessageListenerContainer}, through specifying
 * an external "transactionManager" (typically a
 * {@link org.springframework.transaction.jta.JtaTransactionManager}, with
 * a corresponding XA-aware JMS {@link javax.jms.ConnectionFactory} preplaceded in
 * as "connectionFactory").
 * </ul>
 * Note that XA transaction coordination adds significant runtime overhead,
 * so it might be feasible to avoid it unless absolutely necessary.
 *
 * <p><b>Recommendations:</b>
 * <ul>
 * <li>The general recommendation is to set "sessionTransacted" to "true",
 * typically in combination with local database transactions triggered by the
 * listener implementation, through Spring's standard transaction facilities.
 * This will work nicely in Tomcat or in a standalone environment, often
 * combined with custom duplicate message detection (if it is unacceptable
 * to ever process the same message twice).
 * <li>Alternatively, specify a
 * {@link org.springframework.transaction.jta.JtaTransactionManager} as
 * "transactionManager" for a fully XA-aware JMS provider - typically when
 * running on a Java EE server, but also for other environments with a JTA
 * transaction manager present. This will give full "exactly-once" guarantees
 * without custom duplicate message checks, at the price of additional
 * runtime processing overhead.
 * </ul>
 *
 * <p>Note that the "sessionTransacted" flag is strongly recommended over
 * {@link org.springframework.jms.connection.JmsTransactionManager}, provided
 * that transactions do not need to be managed externally. As a consequence,
 * set the transaction manager only if you are using JTA or if you need to
 * synchronize with custom external transaction arrangements.
 *
 * @author Juergen Hoeller
 * @author Stephane Nicoll
 * @since 2.0
 * @see #setMessageListener
 * @see javax.jms.MessageListener
 * @see SessionAwareMessageListener
 * @see #handleListenerException
 * @see DefaultMessageListenerContainer
 * @see SimpleMessageListenerContainer
 * @see org.springframework.jms.listener.endpoint.JmsMessageEndpointManager
 */
public abstract clreplaced AbstractMessageListenerContainer extends AbstractJmsListeningContainer implements MessageListenerContainer {

    @Nullable
    private volatile Object destination;

    @Nullable
    private volatile String messageSelector;

    @Nullable
    private volatile Object messageListener;

    private boolean subscriptionDurable = false;

    private boolean subscriptionShared = false;

    @Nullable
    private String subscriptionName;

    @Nullable
    private Boolean replyPubSubDomain;

    @Nullable
    private QosSettings replyQosSettings;

    private boolean pubSubNoLocal = false;

    @Nullable
    private MessageConverter messageConverter;

    @Nullable
    private ExceptionListener exceptionListener;

    @Nullable
    private ErrorHandler errorHandler;

    private boolean exposeListenerSession = true;

    private boolean acceptMessagesWhileStopping = false;

    /**
     * Specify concurrency limits.
     */
    public abstract void setConcurrency(String concurrency);

    /**
     * Set the destination to receive messages from.
     * <p>Alternatively, specify a "destinationName", to be dynamically
     * resolved via the {@link org.springframework.jms.support.destination.DestinationResolver}.
     * <p>Note: The destination may be replaced at runtime, with the listener
     * container picking up the new destination immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     * @see #setDestinationName(String)
     */
    public void setDestination(@Nullable Destination destination) {
        this.destination = destination;
        if (destination instanceof Topic && !(destination instanceof Queue)) {
            // Clearly a Topic: let's set the "pubSubDomain" flag accordingly.
            setPubSubDomain(true);
        }
    }

    /**
     * Return the destination to receive messages from. Will be {@code null}
     * if the configured destination is not an actual {@link Destination} type;
     * c.f. {@link #setDestinationName(String) when the destination is a String}.
     */
    @Nullable
    public Destination getDestination() {
        return (this.destination instanceof Destination ? (Destination) this.destination : null);
    }

    /**
     * Set the name of the destination to receive messages from.
     * <p>The specified name will be dynamically resolved via the configured
     * {@link #setDestinationResolver destination resolver}.
     * <p>Alternatively, specify a JMS {@link Destination} object as "destination".
     * <p>Note: The destination may be replaced at runtime, with the listener
     * container picking up the new destination immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     * @see #setDestination(javax.jms.Destination)
     */
    public void setDestinationName(@Nullable String destinationName) {
        this.destination = destinationName;
    }

    /**
     * Return the name of the destination to receive messages from.
     * Will be {@code null} if the configured destination is not a
     * {@link String} type; c.f. {@link #setDestination(Destination) when
     * it is an actual Destination}.
     */
    @Nullable
    public String getDestinationName() {
        return (this.destination instanceof String ? (String) this.destination : null);
    }

    /**
     * Return a descriptive String for this container's JMS destination
     * (never {@code null}).
     */
    protected String getDestinationDescription() {
        Object destination = this.destination;
        return (destination != null ? destination.toString() : "");
    }

    /**
     * Set the JMS message selector expression (or {@code null} if none).
     * Default is none.
     * <p>See the JMS specification for a detailed definition of selector expressions.
     * <p>Note: The message selector may be replaced at runtime, with the listener
     * container picking up the new selector value immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     */
    public void setMessageSelector(@Nullable String messageSelector) {
        this.messageSelector = messageSelector;
    }

    /**
     * Return the JMS message selector expression (or {@code null} if none).
     */
    @Nullable
    public String getMessageSelector() {
        return this.messageSelector;
    }

    /**
     * Set the message listener implementation to register.
     * This can be either a standard JMS {@link MessageListener} object
     * or a Spring {@link SessionAwareMessageListener} object.
     * <p>Note: The message listener may be replaced at runtime, with the listener
     * container picking up the new listener object immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     * @throws IllegalArgumentException if the supplied listener is not a
     * {@link MessageListener} or a {@link SessionAwareMessageListener}
     * @see javax.jms.MessageListener
     * @see SessionAwareMessageListener
     */
    public void setMessageListener(@Nullable Object messageListener) {
        checkMessageListener(messageListener);
        this.messageListener = messageListener;
        if (messageListener != null && this.subscriptionName == null) {
            this.subscriptionName = getDefaultSubscriptionName(messageListener);
        }
    }

    /**
     * Return the message listener object to register.
     */
    @Nullable
    public Object getMessageListener() {
        return this.messageListener;
    }

    /**
     * Check the given message listener, throwing an exception
     * if it does not correspond to a supported listener type.
     * <p>By default, only a standard JMS {@link MessageListener} object or a
     * Spring {@link SessionAwareMessageListener} object will be accepted.
     * @param messageListener the message listener object to check
     * @throws IllegalArgumentException if the supplied listener is not a
     * {@link MessageListener} or a {@link SessionAwareMessageListener}
     * @see javax.jms.MessageListener
     * @see SessionAwareMessageListener
     */
    protected void checkMessageListener(@Nullable Object messageListener) {
        if (messageListener != null && !(messageListener instanceof MessageListener || messageListener instanceof SessionAwareMessageListener)) {
            throw new IllegalArgumentException("Message listener needs to be of type [" + MessageListener.clreplaced.getName() + "] or [" + SessionAwareMessageListener.clreplaced.getName() + "]");
        }
    }

    /**
     * Determine the default subscription name for the given message listener.
     * @param messageListener the message listener object to check
     * @return the default subscription name
     * @see SubscriptionNameProvider
     */
    protected String getDefaultSubscriptionName(Object messageListener) {
        if (messageListener instanceof SubscriptionNameProvider) {
            return ((SubscriptionNameProvider) messageListener).getSubscriptionName();
        } else {
            return messageListener.getClreplaced().getName();
        }
    }

    /**
     * Set whether to make the subscription durable. The durable subscription name
     * to be used can be specified through the "subscriptionName" property.
     * <p>Default is "false". Set this to "true" to register a durable subscription,
     * typically in combination with a "subscriptionName" value (unless
     * your message listener clreplaced name is good enough as subscription name).
     * <p>Only makes sense when listening to a topic (pub-sub domain),
     * therefore this method switches the "pubSubDomain" flag as well.
     * @see #setSubscriptionName
     * @see #setPubSubDomain
     */
    public void setSubscriptionDurable(boolean subscriptionDurable) {
        this.subscriptionDurable = subscriptionDurable;
        if (subscriptionDurable) {
            setPubSubDomain(true);
        }
    }

    /**
     * Return whether to make the subscription durable.
     */
    public boolean isSubscriptionDurable() {
        return this.subscriptionDurable;
    }

    /**
     * Set whether to make the subscription shared. The shared subscription name
     * to be used can be specified through the "subscriptionName" property.
     * <p>Default is "false". Set this to "true" to register a shared subscription,
     * typically in combination with a "subscriptionName" value (unless
     * your message listener clreplaced name is good enough as subscription name).
     * Note that shared subscriptions may also be durable, so this flag can
     * (and often will) be combined with "subscriptionDurable" as well.
     * <p>Only makes sense when listening to a topic (pub-sub domain),
     * therefore this method switches the "pubSubDomain" flag as well.
     * <p><b>Requires a JMS 2.0 compatible message broker.</b>
     * @since 4.1
     * @see #setSubscriptionName
     * @see #setSubscriptionDurable
     * @see #setPubSubDomain
     */
    public void setSubscriptionShared(boolean subscriptionShared) {
        this.subscriptionShared = subscriptionShared;
        if (subscriptionShared) {
            setPubSubDomain(true);
        }
    }

    /**
     * Return whether to make the subscription shared.
     * @since 4.1
     */
    public boolean isSubscriptionShared() {
        return this.subscriptionShared;
    }

    /**
     * Set the name of a subscription to create. To be applied in case
     * of a topic (pub-sub domain) with a shared or durable subscription.
     * <p>The subscription name needs to be unique within this client's
     * JMS client id. Default is the clreplaced name of the specified message listener.
     * <p>Note: Only 1 concurrent consumer (which is the default of this
     * message listener container) is allowed for each subscription,
     * except for a shared subscription (which requires JMS 2.0).
     * @since 4.1
     * @see #setPubSubDomain
     * @see #setSubscriptionDurable
     * @see #setSubscriptionShared
     * @see #setClientId
     * @see #setMessageListener
     */
    public void setSubscriptionName(@Nullable String subscriptionName) {
        this.subscriptionName = subscriptionName;
    }

    /**
     * Return the name of a subscription to create, if any.
     * @since 4.1
     */
    @Nullable
    public String getSubscriptionName() {
        return this.subscriptionName;
    }

    /**
     * Set the name of a durable subscription to create. This method switches
     * to pub-sub domain mode and activates subscription durability as well.
     * <p>The durable subscription name needs to be unique within this client's
     * JMS client id. Default is the clreplaced name of the specified message listener.
     * <p>Note: Only 1 concurrent consumer (which is the default of this
     * message listener container) is allowed for each durable subscription,
     * except for a shared durable subscription (which requires JMS 2.0).
     * @see #setPubSubDomain
     * @see #setSubscriptionDurable
     * @see #setSubscriptionShared
     * @see #setClientId
     * @see #setMessageListener
     */
    public void setDurableSubscriptionName(@Nullable String durableSubscriptionName) {
        this.subscriptionName = durableSubscriptionName;
        this.subscriptionDurable = (durableSubscriptionName != null);
    }

    /**
     * Return the name of a durable subscription to create, if any.
     */
    @Nullable
    public String getDurableSubscriptionName() {
        return (this.subscriptionDurable ? this.subscriptionName : null);
    }

    /**
     * Set whether to inhibit the delivery of messages published by its own connection.
     * Default is "false".
     * @since 4.1
     * @see javax.jms.Session#createConsumer(javax.jms.Destination, String, boolean)
     */
    public void setPubSubNoLocal(boolean pubSubNoLocal) {
        this.pubSubNoLocal = pubSubNoLocal;
    }

    /**
     * Return whether to inhibit the delivery of messages published by its own connection.
     * @since 4.1
     */
    public boolean isPubSubNoLocal() {
        return this.pubSubNoLocal;
    }

    /**
     * Configure the reply destination type. By default, the configured {@code pubSubDomain}
     * value is used (see {@link #isPubSubDomain()}.
     * <p>This setting primarily indicates what type of destination to resolve if dynamic
     * destinations are enabled.
     * @param replyPubSubDomain "true" for the Publish/Subscribe domain ({@link Topic Topics}),
     * "false" for the Point-to-Point domain ({@link Queue Queues})
     * @since 4.2
     * @see #setDestinationResolver
     */
    public void setReplyPubSubDomain(boolean replyPubSubDomain) {
        this.replyPubSubDomain = replyPubSubDomain;
    }

    /**
     * Return whether the Publish/Subscribe domain ({@link javax.jms.Topic Topics}) is used
     * for replies. Otherwise, the Point-to-Point domain ({@link javax.jms.Queue Queues})
     * is used.
     * @since 4.2
     */
    @Override
    public boolean isReplyPubSubDomain() {
        if (this.replyPubSubDomain != null) {
            return this.replyPubSubDomain;
        } else {
            return isPubSubDomain();
        }
    }

    /**
     * Configure the {@link QosSettings} to use when sending a reply. Can be set to
     * {@code null} to indicate that the broker's defaults should be used.
     * @param replyQosSettings the QoS settings to use when sending a reply or {@code null}
     * to use the default vas.
     * @since 5.0
     */
    public void setReplyQosSettings(@Nullable QosSettings replyQosSettings) {
        this.replyQosSettings = replyQosSettings;
    }

    @Override
    @Nullable
    public QosSettings getReplyQosSettings() {
        return this.replyQosSettings;
    }

    /**
     * Set the {@link MessageConverter} strategy for converting JMS Messages.
     * @since 4.1
     */
    public void setMessageConverter(@Nullable MessageConverter messageConverter) {
        this.messageConverter = messageConverter;
    }

    @Override
    @Nullable
    public MessageConverter getMessageConverter() {
        return this.messageConverter;
    }

    /**
     * Set the JMS ExceptionListener to notify in case of a JMSException thrown
     * by the registered message listener or the invocation infrastructure.
     */
    public void setExceptionListener(@Nullable ExceptionListener exceptionListener) {
        this.exceptionListener = exceptionListener;
    }

    /**
     * Return the JMS ExceptionListener to notify in case of a JMSException thrown
     * by the registered message listener or the invocation infrastructure, if any.
     */
    @Nullable
    public ExceptionListener getExceptionListener() {
        return this.exceptionListener;
    }

    /**
     * Set the ErrorHandler to be invoked in case of any uncaught exceptions thrown
     * while processing a Message.
     * <p>By default, there will be <b>no</b> ErrorHandler so that error-level
     * logging is the only result.
     */
    public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Return the ErrorHandler to be invoked in case of any uncaught exceptions thrown
     * while processing a Message.
     * @since 4.1
     */
    @Nullable
    public ErrorHandler getErrorHandler() {
        return this.errorHandler;
    }

    /**
     * Set whether to expose the listener JMS Session to a registered
     * {@link SessionAwareMessageListener} as well as to
     * {@link org.springframework.jms.core.JmsTemplate} calls.
     * <p>Default is "true", reusing the listener's {@link Session}.
     * Turn this off to expose a fresh JMS Session fetched from the same
     * underlying JMS {@link Connection} instead, which might be necessary
     * on some JMS providers.
     * <p>Note that Sessions managed by an external transaction manager will
     * always get exposed to {@link org.springframework.jms.core.JmsTemplate}
     * calls. So in terms of JmsTemplate exposure, this setting only affects
     * locally transacted Sessions.
     * @see SessionAwareMessageListener
     */
    public void setExposeListenerSession(boolean exposeListenerSession) {
        this.exposeListenerSession = exposeListenerSession;
    }

    /**
     * Return whether to expose the listener JMS {@link Session} to a
     * registered {@link SessionAwareMessageListener}.
     */
    public boolean isExposeListenerSession() {
        return this.exposeListenerSession;
    }

    /**
     * Set whether to accept received messages while the listener container
     * in the process of stopping.
     * <p>Default is "false", rejecting such messages through aborting the
     * receive attempt. Switch this flag on to fully process such messages
     * even in the stopping phase, with the drawback that even newly sent
     * messages might still get processed (if coming in before all receive
     * timeouts have expired).
     * <p><b>NOTE:</b> Aborting receive attempts for such incoming messages
     * might lead to the provider's retry count decreasing for the affected
     * messages. If you have a high number of concurrent consumers, make sure
     * that the number of retries is higher than the number of consumers,
     * to be on the safe side for all potential stopping scenarios.
     */
    public void setAcceptMessagesWhileStopping(boolean acceptMessagesWhileStopping) {
        this.acceptMessagesWhileStopping = acceptMessagesWhileStopping;
    }

    /**
     * Return whether to accept received messages while the listener container
     * in the process of stopping.
     */
    public boolean isAcceptMessagesWhileStopping() {
        return this.acceptMessagesWhileStopping;
    }

    @Override
    protected void validateConfiguration() {
        if (this.destination == null) {
            throw new IllegalArgumentException("Property 'destination' or 'destinationName' is required");
        }
    }

    @Override
    public void setupMessageListener(Object messageListener) {
        setMessageListener(messageListener);
    }

    // -------------------------------------------------------------------------
    // Template methods for listener execution
    // -------------------------------------------------------------------------
    /**
     * Execute the specified listener,
     * committing or rolling back the transaction afterwards (if necessary).
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @see #invokeListener
     * @see #commitIfNecessary
     * @see #rollbackOnExceptionIfNecessary
     * @see #handleListenerException
     */
    protected void executeListener(Session session, Message message) {
        try {
            doExecuteListener(session, message);
        } catch (Throwable ex) {
            handleListenerException(ex);
        }
    }

    /**
     * Execute the specified listener,
     * committing or rolling back the transaction afterwards (if necessary).
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see #invokeListener
     * @see #commitIfNecessary
     * @see #rollbackOnExceptionIfNecessary
     * @see #convertJmsAccessException
     */
    protected void doExecuteListener(Session session, Message message) throws JMSException {
        if (!isAcceptMessagesWhileStopping() && !isRunning()) {
            if (logger.isWarnEnabled()) {
                logger.warn("Rejecting received message because of the listener container " + "having been stopped in the meantime: " + message);
            }
            rollbackIfNecessary(session);
            throw new MessageRejectedWhileStoppingException();
        }
        try {
            invokeListener(session, message);
        } catch (JMSException | RuntimeException | Error ex) {
            rollbackOnExceptionIfNecessary(session, ex);
            throw ex;
        }
        commitIfNecessary(session, message);
    }

    /**
     * Invoke the specified listener: either as standard JMS MessageListener
     * or (preferably) as Spring SessionAwareMessageListener.
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see #setMessageListener
     */
    @SuppressWarnings("rawtypes")
    protected void invokeListener(Session session, Message message) throws JMSException {
        Object listener = getMessageListener();
        if (listener instanceof SessionAwareMessageListener) {
            doInvokeListener((SessionAwareMessageListener) listener, session, message);
        } else if (listener instanceof MessageListener) {
            doInvokeListener((MessageListener) listener, message);
        } else if (listener != null) {
            throw new IllegalArgumentException("Only MessageListener and SessionAwareMessageListener supported: " + listener);
        } else {
            throw new IllegalStateException("No message listener specified - see property 'messageListener'");
        }
    }

    /**
     * Invoke the specified listener as Spring SessionAwareMessageListener,
     * exposing a new JMS Session (potentially with its own transaction)
     * to the listener if demanded.
     * @param listener the Spring SessionAwareMessageListener to invoke
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see SessionAwareMessageListener
     * @see #setExposeListenerSession
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected void doInvokeListener(SessionAwareMessageListener listener, Session session, Message message) throws JMSException {
        Connection conToClose = null;
        Session sessionToClose = null;
        try {
            Session sessionToUse = session;
            if (!isExposeListenerSession()) {
                // We need to expose a separate Session.
                conToClose = createConnection();
                sessionToClose = createSession(conToClose);
                sessionToUse = sessionToClose;
            }
            // Actually invoke the message listener...
            listener.onMessage(message, sessionToUse);
            // Clean up specially exposed Session, if any.
            if (sessionToUse != session) {
                if (sessionToUse.getTransacted() && isSessionLocallyTransacted(sessionToUse)) {
                    // Transacted session created by this container -> commit.
                    JmsUtils.commitIfNecessary(sessionToUse);
                }
            }
        } finally {
            JmsUtils.closeSession(sessionToClose);
            JmsUtils.closeConnection(conToClose);
        }
    }

    /**
     * Invoke the specified listener as standard JMS MessageListener.
     * <p>Default implementation performs a plain invocation of the
     * {@code onMessage} method.
     * @param listener the JMS MessageListener to invoke
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see javax.jms.MessageListener#onMessage
     */
    protected void doInvokeListener(MessageListener listener, Message message) throws JMSException {
        listener.onMessage(message);
    }

    /**
     * Perform a commit or message acknowledgement, as appropriate.
     * @param session the JMS Session to commit
     * @param message the Message to acknowledge
     * @throws javax.jms.JMSException in case of commit failure
     */
    protected void commitIfNecessary(Session session, @Nullable Message message) throws JMSException {
        // Commit session or acknowledge message.
        if (session.getTransacted()) {
            // Commit necessary - but avoid commit call within a JTA transaction.
            if (isSessionLocallyTransacted(session)) {
                // Transacted session created by this container -> commit.
                JmsUtils.commitIfNecessary(session);
            }
        } else if (message != null && isClientAcknowledge(session)) {
            message.acknowledge();
        }
    }

    /**
     * Perform a rollback, if appropriate.
     * @param session the JMS Session to rollback
     * @throws javax.jms.JMSException in case of a rollback error
     */
    protected void rollbackIfNecessary(Session session) throws JMSException {
        if (session.getTransacted()) {
            if (isSessionLocallyTransacted(session)) {
                // Transacted session created by this container -> rollback.
                JmsUtils.rollbackIfNecessary(session);
            }
        } else if (isClientAcknowledge(session)) {
            session.recover();
        }
    }

    /**
     * Perform a rollback, handling rollback exceptions properly.
     * @param session the JMS Session to rollback
     * @param ex the thrown application exception or error
     * @throws javax.jms.JMSException in case of a rollback error
     */
    protected void rollbackOnExceptionIfNecessary(Session session, Throwable ex) throws JMSException {
        try {
            if (session.getTransacted()) {
                if (isSessionLocallyTransacted(session)) {
                    // Transacted session created by this container -> rollback.
                    if (logger.isDebugEnabled()) {
                        logger.debug("Initiating transaction rollback on application exception", ex);
                    }
                    JmsUtils.rollbackIfNecessary(session);
                }
            } else if (isClientAcknowledge(session)) {
                session.recover();
            }
        } catch (IllegalStateException ex2) {
            logger.debug("Could not roll back because Session already closed", ex2);
        } catch (JMSException | RuntimeException | Error ex2) {
            logger.error("Application exception overridden by rollback error", ex);
            throw ex2;
        }
    }

    /**
     * Check whether the given Session is locally transacted, that is, whether
     * its transaction is managed by this listener container's Session handling
     * and not by an external transaction coordinator.
     * <p>Note: The Session's own transacted flag will already have been checked
     * before. This method is about finding out whether the Session's transaction
     * is local or externally coordinated.
     * @param session the Session to check
     * @return whether the given Session is locally transacted
     * @see #isSessionTransacted()
     * @see org.springframework.jms.connection.ConnectionFactoryUtils#isSessionTransactional
     */
    protected boolean isSessionLocallyTransacted(Session session) {
        return isSessionTransacted();
    }

    /**
     * Create a JMS MessageConsumer for the given Session and Destination.
     * <p>This implementation uses JMS 1.1 API.
     * @param session the JMS Session to create a MessageConsumer for
     * @param destination the JMS Destination to create a MessageConsumer for
     * @return the new JMS MessageConsumer
     * @throws javax.jms.JMSException if thrown by JMS API methods
     */
    protected MessageConsumer createConsumer(Session session, Destination destination) throws JMSException {
        if (isPubSubDomain() && destination instanceof Topic) {
            if (isSubscriptionShared()) {
                return (isSubscriptionDurable() ? session.createSharedDurableConsumer((Topic) destination, getSubscriptionName(), getMessageSelector()) : session.createSharedConsumer((Topic) destination, getSubscriptionName(), getMessageSelector()));
            } else if (isSubscriptionDurable()) {
                return session.createDurableSubscriber((Topic) destination, getSubscriptionName(), getMessageSelector(), isPubSubNoLocal());
            } else {
                // Only preplaced in the NoLocal flag in case of a Topic (pub-sub mode):
                // Some JMS providers, such as WebSphere MQ 6.0, throw IllegalStateException
                // in case of the NoLocal flag being specified for a Queue.
                return session.createConsumer(destination, getMessageSelector(), isPubSubNoLocal());
            }
        } else {
            return session.createConsumer(destination, getMessageSelector());
        }
    }

    /**
     * Handle the given exception that arose during listener execution.
     * <p>The default implementation logs the exception at warn level,
     * not propagating it to the JMS provider — replaceduming that all handling of
     * acknowledgement and/or transactions is done by this listener container.
     * This can be overridden in subclreplacedes.
     * @param ex the exception to handle
     */
    protected void handleListenerException(Throwable ex) {
        if (ex instanceof MessageRejectedWhileStoppingException) {
            // Internal exception - has been handled before.
            return;
        }
        if (ex instanceof JMSException) {
            invokeExceptionListener((JMSException) ex);
        }
        if (isActive()) {
            // Regular case: failed while active.
            // Invoke ErrorHandler if available.
            invokeErrorHandler(ex);
        } else {
            // Rare case: listener thread failed after container shutdown.
            // Log at debug level, to avoid spamming the shutdown log.
            logger.debug("Listener exception after container shutdown", ex);
        }
    }

    /**
     * Invoke the registered JMS ExceptionListener, if any.
     * @param ex the exception that arose during JMS processing
     * @see #setExceptionListener
     */
    protected void invokeExceptionListener(JMSException ex) {
        ExceptionListener exceptionListener = getExceptionListener();
        if (exceptionListener != null) {
            exceptionListener.onException(ex);
        }
    }

    /**
     * Invoke the registered ErrorHandler, if any. Log at warn level otherwise.
     * @param ex the uncaught error that arose during JMS processing.
     * @see #setErrorHandler
     */
    protected void invokeErrorHandler(Throwable ex) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            errorHandler.handleError(ex);
        } else {
            logger.warn("Execution of JMS message listener failed, and no ErrorHandler has been set.", ex);
        }
    }

    /**
     * Internal exception clreplaced that indicates a rejected message on shutdown.
     * Used to trigger a rollback for an external transaction manager in that case.
     */
    @SuppressWarnings("serial")
    private static clreplaced MessageRejectedWhileStoppingException extends RuntimeException {
    }
}

19 View Source File : TaskUtils.java
License : Apache License 2.0
Project Creator : SourceHot

/**
 * Utility methods for decorating tasks with error handling.
 *
 * <p><b>NOTE:</b> This clreplaced is intended for internal use by Spring's scheduler
 * implementations. It is only public so that it may be accessed from impl clreplacedes
 * within other packages. It is <i>not</i> intended for general use.
 *
 * @author Mark Fisher
 * @author Juergen Hoeller
 * @since 3.0
 */
public abstract clreplaced TaskUtils {

    /**
     * An ErrorHandler strategy that will log the Exception but perform
     * no further handling. This will suppress the error so that
     * subsequent executions of the task will not be prevented.
     */
    public static final ErrorHandler LOG_AND_SUPPRESS_ERROR_HANDLER = new LoggingErrorHandler();

    /**
     * An ErrorHandler strategy that will log at error level and then
     * re-throw the Exception. Note: this will typically prevent subsequent
     * execution of a scheduled task.
     */
    public static final ErrorHandler LOG_AND_PROPAGATE_ERROR_HANDLER = new PropagatingErrorHandler();

    /**
     * Decorate the task for error handling. If the provided {@link ErrorHandler}
     * is not {@code null}, it will be used. Otherwise, repeating tasks will have
     * errors suppressed by default whereas one-shot tasks will have errors
     * propagated by default since those errors may be expected through the
     * returned {@link Future}. In both cases, the errors will be logged.
     */
    public static DelegatingErrorHandlingRunnable decorateTaskWithErrorHandler(Runnable task, @Nullable ErrorHandler errorHandler, boolean isRepeatingTask) {
        if (task instanceof DelegatingErrorHandlingRunnable) {
            return (DelegatingErrorHandlingRunnable) task;
        }
        ErrorHandler eh = (errorHandler != null ? errorHandler : getDefaultErrorHandler(isRepeatingTask));
        return new DelegatingErrorHandlingRunnable(task, eh);
    }

    /**
     * Return the default {@link ErrorHandler} implementation based on the boolean
     * value indicating whether the task will be repeating or not. For repeating tasks
     * it will suppress errors, but for one-time tasks it will propagate. In both
     * cases, the error will be logged.
     */
    public static ErrorHandler getDefaultErrorHandler(boolean isRepeatingTask) {
        return (isRepeatingTask ? LOG_AND_SUPPRESS_ERROR_HANDLER : LOG_AND_PROPAGATE_ERROR_HANDLER);
    }

    /**
     * An {@link ErrorHandler} implementation that logs the Throwable at error
     * level. It does not perform any additional error handling. This can be
     * useful when suppression of errors is the intended behavior.
     */
    private static clreplaced LoggingErrorHandler implements ErrorHandler {

        private final Log logger = LogFactory.getLog(LoggingErrorHandler.clreplaced);

        @Override
        public void handleError(Throwable t) {
            logger.error("Unexpected error occurred in scheduled task", t);
        }
    }

    /**
     * An {@link ErrorHandler} implementation that logs the Throwable at error
     * level and then propagates it.
     */
    private static clreplaced PropagatingErrorHandler extends LoggingErrorHandler {

        @Override
        public void handleError(Throwable t) {
            super.handleError(t);
            ReflectionUtils.rethrowRuntimeException(t);
        }
    }
}

19 View Source File : SimpleApplicationEventMulticaster.java
License : Apache License 2.0
Project Creator : SourceHot

/**
 * Simple implementation of the {@link ApplicationEventMulticaster} interface.
 *
 * <p>Multicasts all events to all registered listeners, leaving it up to
 * the listeners to ignore events that they are not interested in.
 * Listeners will usually perform corresponding {@code instanceof}
 * checks on the preplaceded-in event object.
 *
 * <p>By default, all listeners are invoked in the calling thread.
 * This allows the danger of a rogue listener blocking the entire application,
 * but adds minimal overhead. Specify an alternative task executor to have
 * listeners executed in different threads, for example from a thread pool.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Stephane Nicoll
 * @see #setTaskExecutor
 */
public clreplaced SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

    @Nullable
    private Executor taskExecutor;

    @Nullable
    private ErrorHandler errorHandler;

    /**
     * Create a new SimpleApplicationEventMulticaster.
     */
    public SimpleApplicationEventMulticaster() {
    }

    /**
     * Create a new SimpleApplicationEventMulticaster for the given BeanFactory.
     */
    public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
        setBeanFactory(beanFactory);
    }

    /**
     * Set a custom executor (typically a {@link org.springframework.core.task.TaskExecutor})
     * to invoke each listener with.
     * <p>Default is equivalent to {@link org.springframework.core.task.SyncTaskExecutor},
     * executing all listeners synchronously in the calling thread.
     * <p>Consider specifying an asynchronous task executor here to not block the
     * caller until all listeners have been executed. However, note that asynchronous
     * execution will not participate in the caller's thread context (clreplaced loader,
     * transaction replacedociation) unless the TaskExecutor explicitly supports this.
     * @see org.springframework.core.task.SyncTaskExecutor
     * @see org.springframework.core.task.SimpleAsyncTaskExecutor
     */
    public void setTaskExecutor(@Nullable Executor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * Return the current task executor for this multicaster.
     */
    @Nullable
    protected Executor getTaskExecutor() {
        return this.taskExecutor;
    }

    /**
     * Set the {@link ErrorHandler} to invoke in case an exception is thrown
     * from a listener.
     * <p>Default is none, with a listener exception stopping the current
     * multicast and getting propagated to the publisher of the current event.
     * If a {@linkplain #setTaskExecutor task executor} is specified, each
     * individual listener exception will get propagated to the executor but
     * won't necessarily stop execution of other listeners.
     * <p>Consider setting an {@link ErrorHandler} implementation that catches
     * and logs exceptions (a la
     * {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_SUPPRESS_ERROR_HANDLER})
     * or an implementation that logs exceptions while nevertheless propagating them
     * (e.g. {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_PROPAGATE_ERROR_HANDLER}).
     * @since 4.1
     */
    public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Return the current error handler for this multicaster.
     * @since 4.1
     */
    @Nullable
    protected ErrorHandler getErrorHandler() {
        return this.errorHandler;
    }

    @Override
    public void multicastEvent(ApplicationEvent event) {
        multicastEvent(event, resolveDefaultEventType(event));
    }

    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        Executor executor = getTaskExecutor();
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            } else {
                invokeListener(listener, event);
            }
        }
    }

    private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
        return ResolvableType.forInstance(event);
    }

    /**
     * Invoke the given listener with the given event.
     * @param listener the ApplicationListener to invoke
     * @param event the current event to propagate
     * @since 4.1
     */
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                doInvokeListener(listener, event);
            } catch (Throwable err) {
                errorHandler.handleError(err);
            }
        } else {
            doInvokeListener(listener, event);
        }
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            listener.onApplicationEvent(event);
        } catch (ClreplacedCastException ex) {
            String msg = ex.getMessage();
            if (msg == null || matchesClreplacedCastMessage(msg, event.getClreplaced())) {
                // Possibly a lambda-defined listener which we could not resolve the generic event type for
                // -> let's suppress the exception and just log a debug message.
                Log logger = LogFactory.getLog(getClreplaced());
                if (logger.isTraceEnabled()) {
                    logger.trace("Non-matching event type for listener: " + listener, ex);
                }
            } else {
                throw ex;
            }
        }
    }

    private boolean matchesClreplacedCastMessage(String clreplacedCastMessage, Clreplaced<?> eventClreplaced) {
        // On Java 8, the message starts with the clreplaced name: "java.lang.String cannot be cast..."
        if (clreplacedCastMessage.startsWith(eventClreplaced.getName())) {
            return true;
        }
        // On Java 11, the message starts with "clreplaced ..." a.k.a. Clreplaced.toString()
        if (clreplacedCastMessage.startsWith(eventClreplaced.toString())) {
            return true;
        }
        // On Java 9, the message used to contain the module name: "java.base/java.lang.String cannot be cast..."
        int moduleSeparatorIndex = clreplacedCastMessage.indexOf('/');
        if (moduleSeparatorIndex != -1 && clreplacedCastMessage.startsWith(eventClreplaced.getName(), moduleSeparatorIndex + 1)) {
            return true;
        }
        // replaceduming an unrelated clreplaced cast failure...
        return false;
    }
}

19 View Source File : EmbeddedZooKeeper.java
License : Apache License 2.0
Project Creator : smallFive55

/**
 * from: https://github.com/spring-projects/spring-xd/blob/v1.3.1.RELEASE/spring-xd-dirt/src/main/java/org/springframework/xd/dirt/zookeeper/ZooKeeperUtils.java
 * <p>
 * Helper clreplaced to start an embedded instance of standalone (non clustered) ZooKeeper.
 * <p>
 * NOTE: at least an external standalone server (if not an ensemble) are recommended, even for
 * org.springframework.xd.dirt.server.singlenode.SingleNodeApplication
 *
 * @author Patrick Peralta
 * @author Mark Fisher
 * @author David Turanski
 */
public clreplaced EmbeddedZooKeeper implements SmartLifecycle {

    /**
     * Logger.
     */
    private static final Logger logger = LoggerFactory.getLogger(EmbeddedZooKeeper.clreplaced);

    /**
     * ZooKeeper client port. This will be determined dynamically upon startup.
     */
    private final int clientPort;

    /**
     * Whether to auto-start. Default is true.
     */
    private boolean autoStartup = true;

    /**
     * Lifecycle phase. Default is 0.
     */
    private int phase = 0;

    /**
     * Thread for running the ZooKeeper server.
     */
    private volatile Thread zkServerThread;

    /**
     * ZooKeeper server.
     */
    private volatile ZooKeeperServerMain zkServer;

    /**
     * {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread.
     */
    private ErrorHandler errorHandler;

    private boolean daemon = true;

    /**
     * Construct an EmbeddedZooKeeper with a random port.
     */
    public EmbeddedZooKeeper() {
        clientPort = SocketUtils.findAvailableTcpPort();
    }

    /**
     * Construct an EmbeddedZooKeeper with the provided port.
     *
     * @param clientPort port for ZooKeeper server to bind to
     */
    public EmbeddedZooKeeper(int clientPort, boolean daemon) {
        this.clientPort = clientPort;
        this.daemon = daemon;
    }

    /**
     * Returns the port that clients should use to connect to this embedded server.
     *
     * @return dynamically determined client port
     */
    public int getClientPort() {
        return this.clientPort;
    }

    /**
     * Specify whether to start automatically. Default is true.
     *
     * @param autoStartup whether to start automatically
     */
    public void setAutoStartup(boolean autoStartup) {
        this.autoStartup = autoStartup;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAutoStartup() {
        return this.autoStartup;
    }

    /**
     * Specify the lifecycle phase for the embedded server.
     *
     * @param phase the lifecycle phase
     */
    public void setPhase(int phase) {
        this.phase = phase;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getPhase() {
        return this.phase;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isRunning() {
        return (zkServerThread != null);
    }

    /**
     * Start the ZooKeeper server in a background thread.
     * <p>
     * Register an error handler via {@link #setErrorHandler} in order to handle
     * any exceptions thrown during startup or execution.
     */
    @Override
    public synchronized void start() {
        if (zkServerThread == null) {
            zkServerThread = new Thread(new ServerRunnable(), "ZooKeeper Server Starter");
            zkServerThread.setDaemon(daemon);
            zkServerThread.start();
        }
    }

    /**
     * Shutdown the ZooKeeper server.
     */
    @Override
    public synchronized void stop() {
        if (zkServerThread != null) {
            // The shutdown method is protected...thus this hack to invoke it.
            // This will log an exception on shutdown; see
            // https://issues.apache.org/jira/browse/ZOOKEEPER-1873 for details.
            try {
                Method shutdown = ZooKeeperServerMain.clreplaced.getDeclaredMethod("shutdown");
                shutdown.setAccessible(true);
                shutdown.invoke(zkServer);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            // It is expected that the thread will exit after
            // the server is shutdown; this will block until
            // the shutdown is complete.
            try {
                zkServerThread.join(5000);
                zkServerThread = null;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                logger.warn("Interrupted while waiting for embedded ZooKeeper to exit");
                // abandoning zk thread
                zkServerThread = null;
            }
        }
    }

    /**
     * Stop the server if running and invoke the callback when complete.
     */
    @Override
    public void stop(Runnable callback) {
        stop();
        callback.run();
    }

    /**
     * Provide an {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread. If none
     * is provided, only error-level logging will occur.
     *
     * @param errorHandler the {@link ErrorHandler} to be invoked
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Runnable implementation that starts the ZooKeeper server.
     */
    private clreplaced ServerRunnable implements Runnable {

        @Override
        public void run() {
            try {
                Properties properties = new Properties();
                File file = new File(System.getProperty("java.io.tmpdir") + File.separator + UUID.randomUUID());
                file.deleteOnExit();
                properties.setProperty("dataDir", file.getAbsolutePath());
                properties.setProperty("clientPort", String.valueOf(clientPort));
                QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig();
                quorumPeerConfig.parseProperties(properties);
                zkServer = new ZooKeeperServerMain();
                ServerConfig configuration = new ServerConfig();
                configuration.readFrom(quorumPeerConfig);
                zkServer.runFromConfig(configuration);
            } catch (Exception e) {
                if (errorHandler != null) {
                    errorHandler.handleError(e);
                } else {
                    logger.error("Exception running embedded ZooKeeper", e);
                }
            }
        }
    }
}

19 View Source File : EmbeddedZooKeeper.java
License : Apache License 2.0
Project Creator : smallFive55

/**
 * Provide an {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread. If none
 * is provided, only error-level logging will occur.
 *
 * @param errorHandler the {@link ErrorHandler} to be invoked
 */
public void setErrorHandler(ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

19 View Source File : ProxyWebSocketHandler.java
License : Apache License 2.0
Project Creator : mthizo247

/**
 * A {@link WebSocketHandlerDecorator} that adds web socket support to zuul reverse proxy.
 *
 * @author Ronald Mthombeni
 * @author Salman Noor
 */
public clreplaced ProxyWebSocketHandler extends WebSocketHandlerDecorator {

    private final Logger logger = LoggerFactory.getLogger(ProxyWebSocketHandler.clreplaced);

    private final WebSocketHttpHeadersCallback headersCallback;

    private final SimpMessagingTemplate messagingTemplate;

    private final ProxyTargetResolver proxyTargetResolver;

    private final ZuulWebSocketProperties zuulWebSocketProperties;

    private final WebSocketStompClient stompClient;

    private final Map<WebSocketSession, ProxyWebSocketConnectionManager> managers = new ConcurrentHashMap<>();

    private ErrorHandler errorHandler;

    public ProxyWebSocketHandler(WebSocketHandler delegate, WebSocketStompClient stompClient, WebSocketHttpHeadersCallback headersCallback, SimpMessagingTemplate messagingTemplate, ProxyTargetResolver proxyTargetResolver, ZuulWebSocketProperties zuulWebSocketProperties) {
        super(delegate);
        this.stompClient = stompClient;
        this.headersCallback = headersCallback;
        this.messagingTemplate = messagingTemplate;
        this.proxyTargetResolver = proxyTargetResolver;
        this.zuulWebSocketProperties = zuulWebSocketProperties;
    }

    public void errorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    private String getWebSocketServerPath(ZuulWebSocketProperties.WsBrokerage wsBrokerage, URI uri) {
        String path = uri.toString();
        if (path.contains(":")) {
            path = UriComponentsBuilder.fromUriString(path).build().getPath();
        }
        for (String endPoint : wsBrokerage.getEndPoints()) {
            if (PatternMatchUtils.simpleMatch(toPattern(endPoint), path + "/")) {
                return endPoint;
            }
        }
        return null;
    }

    private ZuulWebSocketProperties.WsBrokerage getWebSocketBrokarage(URI uri) {
        String path = uri.toString();
        if (path.contains(":")) {
            path = UriComponentsBuilder.fromUriString(path).build().getPath();
        }
        for (Map.Entry<String, ZuulWebSocketProperties.WsBrokerage> entry : zuulWebSocketProperties.getBrokerages().entrySet()) {
            ZuulWebSocketProperties.WsBrokerage wsBrokerage = entry.getValue();
            if (wsBrokerage.isEnabled()) {
                for (String endPoint : wsBrokerage.getEndPoints()) {
                    if (PatternMatchUtils.simpleMatch(toPattern(endPoint), path + "/")) {
                        return wsBrokerage;
                    }
                }
            }
        }
        return null;
    }

    private String toPattern(String path) {
        path = path.startsWith("/") ? "**" + path : "**/" + path;
        return path.endsWith("/") ? path + "**" : path + "/**";
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        disconnectFromProxiedTarget(session);
        super.afterConnectionClosed(session, closeStatus);
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        super.handleMessage(session, message);
        handleMessageFromClient(session, message);
    }

    private void handleMessageFromClient(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        boolean handled = false;
        WebSocketMessageAccessor accessor = WebSocketMessageAccessor.create(message);
        if (StompCommand.SEND.toString().equalsIgnoreCase(accessor.getCommand())) {
            handled = true;
            sendMessageToProxiedTarget(session, accessor);
        }
        if (StompCommand.SUBSCRIBE.toString().equalsIgnoreCase(accessor.getCommand())) {
            handled = true;
            subscribeToProxiedTarget(session, accessor);
        }
        if (StompCommand.UNSUBSCRIBE.toString().equalsIgnoreCase(accessor.getCommand())) {
            handled = true;
            unsubscribeFromProxiedTarget(session, accessor);
        }
        if (StompCommand.CONNECT.toString().equalsIgnoreCase(accessor.getCommand())) {
            handled = true;
            connectToProxiedTarget(session);
        }
        if (!handled) {
            if (logger.isDebugEnabled()) {
                logger.debug("STOMP COMMAND " + accessor.getCommand() + " was not explicitly handled");
            }
        }
    }

    private void connectToProxiedTarget(WebSocketSession session) {
        URI sessionUri = session.getUri();
        ZuulWebSocketProperties.WsBrokerage wsBrokerage = getWebSocketBrokarage(sessionUri);
        replacedert.notNull(wsBrokerage, "wsBrokerage must not be null");
        String path = getWebSocketServerPath(wsBrokerage, sessionUri);
        replacedert.notNull(path, "Web socket uri path must be null");
        URI routeTarget = proxyTargetResolver.resolveTarget(wsBrokerage);
        replacedert.notNull(routeTarget, "routeTarget must not be null");
        String uri = ServletUriComponentsBuilder.fromUri(routeTarget).path(path).replaceQuery(sessionUri.getQuery()).toUriString();
        ProxyWebSocketConnectionManager connectionManager = new ProxyWebSocketConnectionManager(messagingTemplate, stompClient, session, headersCallback, uri);
        connectionManager.errorHandler(this.errorHandler);
        managers.put(session, connectionManager);
        connectionManager.start();
    }

    private void disconnectFromProxiedTarget(WebSocketSession session) {
        disconnectProxyManager(managers.remove(session));
    }

    private void disconnectProxyManager(ProxyWebSocketConnectionManager proxyManager) {
        if (proxyManager != null) {
            try {
                proxyManager.disconnect();
            } catch (Throwable ignored) {
            // nothing
            }
        }
    }

    private void unsubscribeFromProxiedTarget(WebSocketSession session, WebSocketMessageAccessor accessor) {
        ProxyWebSocketConnectionManager manager = managers.get(session);
        if (manager != null) {
            manager.unsubscribe(accessor.getDestination());
        }
    }

    private void sendMessageToProxiedTarget(WebSocketSession session, WebSocketMessageAccessor accessor) {
        ProxyWebSocketConnectionManager manager = managers.get(session);
        manager.sendMessage(accessor.getDestination(), accessor.getPayload());
    }

    private void subscribeToProxiedTarget(WebSocketSession session, WebSocketMessageAccessor accessor) throws Exception {
        ProxyWebSocketConnectionManager manager = managers.get(session);
        manager.subscribe(accessor.getDestination());
    }
}

19 View Source File : ProxyWebSocketHandler.java
License : Apache License 2.0
Project Creator : mthizo247

public void errorHandler(ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

19 View Source File : SimpleApplicationEventMulticaster.java
License : MIT License
Project Creator : mindcarver

/**
 * Simple implementation of the {@link ApplicationEventMulticaster} interface.
 *
 * <p>Multicasts all events to all registered listeners, leaving it up to
 * the listeners to ignore events that they are not interested in.
 * Listeners will usually perform corresponding {@code instanceof}
 * checks on the preplaceded-in event object.
 *
 * <p>By default, all listeners are invoked in the calling thread.
 * This allows the danger of a rogue listener blocking the entire application,
 * but adds minimal overhead. Specify an alternative task executor to have
 * listeners executed in different threads, for example from a thread pool.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Stephane Nicoll
 * @see #setTaskExecutor
 */
public clreplaced SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

    @Nullable
    private Executor taskExecutor;

    @Nullable
    private ErrorHandler errorHandler;

    /**
     * Create a new SimpleApplicationEventMulticaster.
     */
    public SimpleApplicationEventMulticaster() {
    }

    /**
     * Create a new SimpleApplicationEventMulticaster for the given BeanFactory.
     */
    public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
        setBeanFactory(beanFactory);
    }

    /**
     * Set a custom executor (typically a {@link org.springframework.core.task.TaskExecutor})
     * to invoke each listener with.
     * <p>Default is equivalent to {@link org.springframework.core.task.SyncTaskExecutor},
     * executing all listeners synchronously in the calling thread.
     * <p>Consider specifying an asynchronous task executor here to not block the
     * caller until all listeners have been executed. However, note that asynchronous
     * execution will not participate in the caller's thread context (clreplaced loader,
     * transaction replacedociation) unless the TaskExecutor explicitly supports this.
     * @see org.springframework.core.task.SyncTaskExecutor
     * @see org.springframework.core.task.SimpleAsyncTaskExecutor
     */
    public void setTaskExecutor(@Nullable Executor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * Return the current task executor for this multicaster.
     */
    @Nullable
    protected Executor getTaskExecutor() {
        return this.taskExecutor;
    }

    /**
     * Set the {@link ErrorHandler} to invoke in case an exception is thrown
     * from a listener.
     * <p>Default is none, with a listener exception stopping the current
     * multicast and getting propagated to the publisher of the current event.
     * If a {@linkplain #setTaskExecutor task executor} is specified, each
     * individual listener exception will get propagated to the executor but
     * won't necessarily stop execution of other listeners.
     * <p>Consider setting an {@link ErrorHandler} implementation that catches
     * and logs exceptions (a la
     * {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_SUPPRESS_ERROR_HANDLER})
     * or an implementation that logs exceptions while nevertheless propagating them
     * (e.g. {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_PROPAGATE_ERROR_HANDLER}).
     * @since 4.1
     */
    public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Return the current error handler for this multicaster.
     * @since 4.1
     */
    @Nullable
    protected ErrorHandler getErrorHandler() {
        return this.errorHandler;
    }

    @Override
    public void multicastEvent(ApplicationEvent event) {
        multicastEvent(event, resolveDefaultEventType(event));
    }

    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            } else {
                invokeListener(listener, event);
            }
        }
    }

    private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
        return ResolvableType.forInstance(event);
    }

    /**
     * Invoke the given listener with the given event.
     * @param listener the ApplicationListener to invoke
     * @param event the current event to propagate
     * @since 4.1
     */
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                doInvokeListener(listener, event);
            } catch (Throwable err) {
                errorHandler.handleError(err);
            }
        } else {
            doInvokeListener(listener, event);
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            listener.onApplicationEvent(event);
        } catch (ClreplacedCastException ex) {
            String msg = ex.getMessage();
            if (msg == null || matchesClreplacedCastMessage(msg, event.getClreplaced())) {
                // Possibly a lambda-defined listener which we could not resolve the generic event type for
                // -> let's suppress the exception and just log a debug message.
                Log logger = LogFactory.getLog(getClreplaced());
                if (logger.isDebugEnabled()) {
                    logger.debug("Non-matching event type for listener: " + listener, ex);
                }
            } else {
                throw ex;
            }
        }
    }

    private boolean matchesClreplacedCastMessage(String clreplacedCastMessage, Clreplaced<?> eventClreplaced) {
        // On Java 8, the message starts with the clreplaced name: "java.lang.String cannot be cast..."
        if (clreplacedCastMessage.startsWith(eventClreplaced.getName())) {
            return true;
        }
        // On Java 11, the message starts with "clreplaced ..." a.k.a. Clreplaced.toString()
        if (clreplacedCastMessage.startsWith(eventClreplaced.toString())) {
            return true;
        }
        // On Java 9, the message used to contain the module name: "java.base/java.lang.String cannot be cast..."
        int moduleSeparatorIndex = clreplacedCastMessage.indexOf('/');
        if (moduleSeparatorIndex != -1 && clreplacedCastMessage.startsWith(eventClreplaced.getName(), moduleSeparatorIndex + 1)) {
            return true;
        }
        // replaceduming an unrelated clreplaced cast failure...
        return false;
    }
}

19 View Source File : SimpleMessageListenerContainerTests.java
License : Apache License 2.0
Project Creator : langtianya

@Test
public void testRegisteredErrorHandlerIsInvokedOnException() throws Exception {
    final SimpleMessageConsumer messageConsumer = new SimpleMessageConsumer();
    Session session = mock(Session.clreplaced);
    // Queue gets created in order to create MessageConsumer for that Destination...
    given(session.createQueue(DESTINATION_NAME)).willReturn(QUEUE_DESTINATION);
    // and then the MessageConsumer gets created...
    // no MessageSelector...
    given(session.createConsumer(QUEUE_DESTINATION, null)).willReturn(messageConsumer);
    // an exception is thrown, so the rollback logic is being applied here...
    given(session.getTransacted()).willReturn(false);
    Connection connection = mock(Connection.clreplaced);
    // session gets created in order to register MessageListener...
    given(connection.createSession(this.container.isSessionTransacted(), this.container.getSessionAcknowledgeMode())).willReturn(session);
    ConnectionFactory connectionFactory = mock(ConnectionFactory.clreplaced);
    given(connectionFactory.createConnection()).willReturn(connection);
    final IllegalStateException theException = new IllegalStateException("intentional test failure");
    this.container.setConnectionFactory(connectionFactory);
    this.container.setDestinationName(DESTINATION_NAME);
    this.container.setMessageListener(new SessionAwareMessageListener<Message>() {

        @Override
        public void onMessage(Message message, Session session) throws JMSException {
            throw theException;
        }
    });
    ErrorHandler errorHandler = mock(ErrorHandler.clreplaced);
    this.container.setErrorHandler(errorHandler);
    this.container.afterPropertiesSet();
    this.container.start();
    // manually trigger an Exception with the above bad MessageListener...
    Message message = mock(Message.clreplaced);
    // a Throwable from a MessageListener MUST simply be swallowed...
    messageConsumer.sendMessage(message);
    verify(connection).setExceptionListener(this.container);
    verify(connection).start();
    verify(errorHandler).handleError(theException);
}

19 View Source File : AbstractMessageListenerContainer.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Abstract base clreplaced for Spring message listener container implementations.
 * Can either host a standard JMS {@link javax.jms.MessageListener} or Spring's
 * {@link SessionAwareMessageListener} for actual message processing.
 *
 * <p>Usually holds a single JMS {@link Connection} that all listeners are supposed
 * to be registered on, which is the standard JMS way of managing listener sessions.
 * Can alternatively also be used with a fresh Connection per listener, for Java EE
 * style XA-aware JMS messaging. The actual registration process is up to concrete
 * subclreplacedes.
 *
 * <p><b>NOTE:</b> The default behavior of this message listener container is to
 * <b>never</b> propagate an exception thrown by a message listener up to the JMS
 * provider. Instead, it will log any such exception at the error level.
 * This means that from the perspective of the attendant JMS provider no such
 * listener will ever fail. However, if error handling is necessary, then
 * any implementation of the {@link ErrorHandler} strategy may be provided to
 * the {@link #setErrorHandler(ErrorHandler)} method. Note that JMSExceptions
 * <b>will</b> be preplaceded to the ErrorHandler in addition to (but after) being
 * preplaceded to an {@link ExceptionListener}, if one has been provided.
 *
 * <p>The listener container offers the following message acknowledgment options:
 * <ul>
 * <li>"sessionAcknowledgeMode" set to "AUTO_ACKNOWLEDGE" (default):
 * This mode is container-dependent: For {@link DefaultMessageListenerContainer},
 * it means automatic message acknowledgment <i>before</i> listener execution, with
 * no redelivery in case of an exception and no redelivery in case of other listener
 * execution interruptions either. For {@link SimpleMessageListenerContainer},
 * it means automatic message acknowledgment <i>after</i> listener execution, with
 * no redelivery in case of a user exception thrown but potential redelivery in case
 * of the JVM dying during listener execution. In order to consistently arrange for
 * redelivery with any container variant, consider "CLIENT_ACKNOWLEDGE" mode or -
 * preferably - setting "sessionTransacted" to "true" instead.
 * <li>"sessionAcknowledgeMode" set to "DUPS_OK_ACKNOWLEDGE":
 * <i>Lazy</i> message acknowledgment during ({@link DefaultMessageListenerContainer})
 * or shortly after ({@link SimpleMessageListenerContainer}) listener execution;
 * no redelivery in case of a user exception thrown but potential redelivery in case
 * of the JVM dying during listener execution. In order to consistently arrange for
 * redelivery with any container variant, consider "CLIENT_ACKNOWLEDGE" mode or -
 * preferably - setting "sessionTransacted" to "true" instead.
 * <li>"sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE":
 * Automatic message acknowledgment <i>after</i> successful listener execution;
 * best-effort redelivery in case of a user exception thrown as well as in case
 * of other listener execution interruptions (such as the JVM dying).
 * <li>"sessionTransacted" set to "true":
 * Transactional acknowledgment after successful listener execution;
 * <i>guaranteed redelivery</i> in case of a user exception thrown as well as
 * in case of other listener execution interruptions (such as the JVM dying).
 * </ul>
 *
 * <p>There are two solutions to the duplicate message processing problem:
 * <ul>
 * <li>Either add <i>duplicate message detection</i> to your listener, in the
 * form of a business enreplacedy existence check or a protocol table check. This
 * usually just needs to be done in case of the JMSRedelivered flag being
 * set on the incoming message (otherwise just process straightforwardly).
 * Note that with "sessionTransacted" set to "true", duplicate messages will
 * only appear in case of the JVM dying at the most unfortunate point possible
 * (i.e. after your business logic executed but before the JMS part got committed),
 * so duplicate message detection is just there to cover a corner case.
 * <li>Or wrap your <i>entire processing with an XA transaction</i>, covering the
 * reception of the JMS message as well as the execution of the business logic in
 * your message listener (including database operations etc). This is only
 * supported by {@link DefaultMessageListenerContainer}, through specifying
 * an external "transactionManager" (typically a
 * {@link org.springframework.transaction.jta.JtaTransactionManager}, with
 * a corresponding XA-aware JMS {@link javax.jms.ConnectionFactory} preplaceded in
 * as "connectionFactory").
 * </ul>
 * Note that XA transaction coordination adds significant runtime overhead,
 * so it might be feasible to avoid it unless absolutely necessary.
 *
 * <p><b>Recommendations:</b>
 * <ul>
 * <li>The general recommendation is to set "sessionTransacted" to "true",
 * typically in combination with local database transactions triggered by the
 * listener implementation, through Spring's standard transaction facilities.
 * This will work nicely in Tomcat or in a standalone environment, often
 * combined with custom duplicate message detection (if it is unacceptable
 * to ever process the same message twice).
 * <li>Alternatively, specify a
 * {@link org.springframework.transaction.jta.JtaTransactionManager} as
 * "transactionManager" for a fully XA-aware JMS provider - typically when
 * running on a Java EE server, but also for other environments with a JTA
 * transaction manager present. This will give full "exactly-once" guarantees
 * without custom duplicate message checks, at the price of additional
 * runtime processing overhead.
 * </ul>
 *
 * <p>Note that the "sessionTransacted" flag is strongly recommended over
 * {@link org.springframework.jms.connection.JmsTransactionManager}, provided
 * that transactions do not need to be managed externally. As a consequence,
 * set the transaction manager only if you are using JTA or if you need to
 * synchronize with custom external transaction arrangements.
 *
 * @author Juergen Hoeller
 * @author Stephane Nicoll
 * @since 2.0
 * @see #setMessageListener
 * @see javax.jms.MessageListener
 * @see SessionAwareMessageListener
 * @see #handleListenerException
 * @see DefaultMessageListenerContainer
 * @see SimpleMessageListenerContainer
 * @see org.springframework.jms.listener.endpoint.JmsMessageEndpointManager
 */
public abstract clreplaced AbstractMessageListenerContainer extends AbstractJmsListeningContainer implements MessageListenerContainer {

    /**
     * The JMS 2.0 Session.createSharedConsumer method, if available
     */
    private static final Method createSharedConsumerMethod = ClreplacedUtils.getMethodIfAvailable(Session.clreplaced, "createSharedConsumer", Topic.clreplaced, String.clreplaced, String.clreplaced);

    /**
     * The JMS 2.0 Session.createSharedDurableConsumer method, if available
     */
    private static final Method createSharedDurableConsumerMethod = ClreplacedUtils.getMethodIfAvailable(Session.clreplaced, "createSharedDurableConsumer", Topic.clreplaced, String.clreplaced, String.clreplaced);

    private volatile Object destination;

    private volatile String messageSelector;

    private volatile Object messageListener;

    private boolean subscriptionDurable = false;

    private boolean subscriptionShared = false;

    private String subscriptionName;

    private Boolean replyPubSubDomain;

    private boolean pubSubNoLocal = false;

    private MessageConverter messageConverter;

    private ExceptionListener exceptionListener;

    private ErrorHandler errorHandler;

    private boolean exposeListenerSession = true;

    private boolean acceptMessagesWhileStopping = false;

    /**
     * Specify concurrency limits.
     */
    public abstract void setConcurrency(String concurrency);

    /**
     * Set the destination to receive messages from.
     * <p>Alternatively, specify a "destinationName", to be dynamically
     * resolved via the {@link org.springframework.jms.support.destination.DestinationResolver}.
     * <p>Note: The destination may be replaced at runtime, with the listener
     * container picking up the new destination immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     * @see #setDestinationName(String)
     */
    public void setDestination(Destination destination) {
        replacedert.notNull(destination, "'destination' must not be null");
        this.destination = destination;
        if (destination instanceof Topic && !(destination instanceof Queue)) {
            // Clearly a Topic: let's set the "pubSubDomain" flag accordingly.
            setPubSubDomain(true);
        }
    }

    /**
     * Return the destination to receive messages from. Will be {@code null}
     * if the configured destination is not an actual {@link Destination} type;
     * c.f. {@link #setDestinationName(String) when the destination is a String}.
     */
    public Destination getDestination() {
        return (this.destination instanceof Destination ? (Destination) this.destination : null);
    }

    /**
     * Set the name of the destination to receive messages from.
     * <p>The specified name will be dynamically resolved via the configured
     * {@link #setDestinationResolver destination resolver}.
     * <p>Alternatively, specify a JMS {@link Destination} object as "destination".
     * <p>Note: The destination may be replaced at runtime, with the listener
     * container picking up the new destination immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     * @param destinationName the desired destination (can be {@code null})
     * @see #setDestination(javax.jms.Destination)
     */
    public void setDestinationName(String destinationName) {
        replacedert.notNull(destinationName, "'destinationName' must not be null");
        this.destination = destinationName;
    }

    /**
     * Return the name of the destination to receive messages from.
     * Will be {@code null} if the configured destination is not a
     * {@link String} type; c.f. {@link #setDestination(Destination) when
     * it is an actual Destination}.
     */
    public String getDestinationName() {
        return (this.destination instanceof String ? (String) this.destination : null);
    }

    /**
     * Return a descriptive String for this container's JMS destination
     * (never {@code null}).
     */
    protected String getDestinationDescription() {
        return this.destination.toString();
    }

    /**
     * Set the JMS message selector expression (or {@code null} if none).
     * Default is none.
     * <p>See the JMS specification for a detailed definition of selector expressions.
     * <p>Note: The message selector may be replaced at runtime, with the listener
     * container picking up the new selector value immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     */
    public void setMessageSelector(String messageSelector) {
        this.messageSelector = messageSelector;
    }

    /**
     * Return the JMS message selector expression (or {@code null} if none).
     */
    public String getMessageSelector() {
        return this.messageSelector;
    }

    /**
     * Set the message listener implementation to register.
     * This can be either a standard JMS {@link MessageListener} object
     * or a Spring {@link SessionAwareMessageListener} object.
     * <p>Note: The message listener may be replaced at runtime, with the listener
     * container picking up the new listener object immediately (works e.g. with
     * DefaultMessageListenerContainer, as long as the cache level is less than
     * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
     * @throws IllegalArgumentException if the supplied listener is not a
     * {@link MessageListener} or a {@link SessionAwareMessageListener}
     * @see javax.jms.MessageListener
     * @see SessionAwareMessageListener
     */
    public void setMessageListener(Object messageListener) {
        checkMessageListener(messageListener);
        this.messageListener = messageListener;
        if (this.subscriptionName == null) {
            this.subscriptionName = getDefaultSubscriptionName(messageListener);
        }
    }

    /**
     * Return the message listener object to register.
     */
    public Object getMessageListener() {
        return this.messageListener;
    }

    /**
     * Check the given message listener, throwing an exception
     * if it does not correspond to a supported listener type.
     * <p>By default, only a standard JMS {@link MessageListener} object or a
     * Spring {@link SessionAwareMessageListener} object will be accepted.
     * @param messageListener the message listener object to check
     * @throws IllegalArgumentException if the supplied listener is not a
     * {@link MessageListener} or a {@link SessionAwareMessageListener}
     * @see javax.jms.MessageListener
     * @see SessionAwareMessageListener
     */
    protected void checkMessageListener(Object messageListener) {
        if (!(messageListener instanceof MessageListener || messageListener instanceof SessionAwareMessageListener)) {
            throw new IllegalArgumentException("Message listener needs to be of type [" + MessageListener.clreplaced.getName() + "] or [" + SessionAwareMessageListener.clreplaced.getName() + "]");
        }
    }

    /**
     * Determine the default subscription name for the given message listener.
     * @param messageListener the message listener object to check
     * @return the default subscription name
     * @see SubscriptionNameProvider
     */
    protected String getDefaultSubscriptionName(Object messageListener) {
        if (messageListener instanceof SubscriptionNameProvider) {
            return ((SubscriptionNameProvider) messageListener).getSubscriptionName();
        } else {
            return messageListener.getClreplaced().getName();
        }
    }

    /**
     * Set whether to make the subscription durable. The durable subscription name
     * to be used can be specified through the "subscriptionName" property.
     * <p>Default is "false". Set this to "true" to register a durable subscription,
     * typically in combination with a "subscriptionName" value (unless
     * your message listener clreplaced name is good enough as subscription name).
     * <p>Only makes sense when listening to a topic (pub-sub domain),
     * therefore this method switches the "pubSubDomain" flag as well.
     * @see #setSubscriptionName
     * @see #setPubSubDomain
     */
    public void setSubscriptionDurable(boolean subscriptionDurable) {
        this.subscriptionDurable = subscriptionDurable;
        if (subscriptionDurable) {
            setPubSubDomain(true);
        }
    }

    /**
     * Return whether to make the subscription durable.
     */
    public boolean isSubscriptionDurable() {
        return this.subscriptionDurable;
    }

    /**
     * Set whether to make the subscription shared. The shared subscription name
     * to be used can be specified through the "subscriptionName" property.
     * <p>Default is "false". Set this to "true" to register a shared subscription,
     * typically in combination with a "subscriptionName" value (unless
     * your message listener clreplaced name is good enough as subscription name).
     * Note that shared subscriptions may also be durable, so this flag can
     * (and often will) be combined with "subscriptionDurable" as well.
     * <p>Only makes sense when listening to a topic (pub-sub domain),
     * therefore this method switches the "pubSubDomain" flag as well.
     * <p><b>Requires a JMS 2.0 compatible message broker.</b>
     * @since 4.1
     * @see #setSubscriptionName
     * @see #setSubscriptionDurable
     * @see #setPubSubDomain
     */
    public void setSubscriptionShared(boolean subscriptionShared) {
        this.subscriptionShared = subscriptionShared;
        if (subscriptionShared) {
            setPubSubDomain(true);
        }
    }

    /**
     * Return whether to make the subscription shared.
     * @since 4.1
     */
    public boolean isSubscriptionShared() {
        return this.subscriptionShared;
    }

    /**
     * Set the name of a subscription to create. To be applied in case
     * of a topic (pub-sub domain) with a shared or durable subscription.
     * <p>The subscription name needs to be unique within this client's
     * JMS client id. Default is the clreplaced name of the specified message listener.
     * <p>Note: Only 1 concurrent consumer (which is the default of this
     * message listener container) is allowed for each subscription,
     * except for a shared subscription (which requires JMS 2.0).
     * @since 4.1
     * @see #setPubSubDomain
     * @see #setSubscriptionDurable
     * @see #setSubscriptionShared
     * @see #setClientId
     * @see #setMessageListener
     */
    public void setSubscriptionName(String subscriptionName) {
        this.subscriptionName = subscriptionName;
    }

    /**
     * Return the name of a subscription to create, if any.
     * @since 4.1
     */
    public String getSubscriptionName() {
        return this.subscriptionName;
    }

    /**
     * Set the name of a durable subscription to create. This method switches
     * to pub-sub domain mode and activates subscription durability as well.
     * <p>The durable subscription name needs to be unique within this client's
     * JMS client id. Default is the clreplaced name of the specified message listener.
     * <p>Note: Only 1 concurrent consumer (which is the default of this
     * message listener container) is allowed for each durable subscription,
     * except for a shared durable subscription (which requires JMS 2.0).
     * @see #setPubSubDomain
     * @see #setSubscriptionDurable
     * @see #setSubscriptionShared
     * @see #setClientId
     * @see #setMessageListener
     */
    public void setDurableSubscriptionName(String durableSubscriptionName) {
        this.subscriptionName = durableSubscriptionName;
        this.subscriptionDurable = true;
    }

    /**
     * Return the name of a durable subscription to create, if any.
     */
    public String getDurableSubscriptionName() {
        return (this.subscriptionDurable ? this.subscriptionName : null);
    }

    /**
     * Set whether to inhibit the delivery of messages published by its own connection.
     * Default is "false".
     * @since 4.1
     * @see javax.jms.Session#createConsumer(javax.jms.Destination, String, boolean)
     */
    public void setPubSubNoLocal(boolean pubSubNoLocal) {
        this.pubSubNoLocal = pubSubNoLocal;
    }

    /**
     * Return whether to inhibit the delivery of messages published by its own connection.
     * @since 4.1
     */
    public boolean isPubSubNoLocal() {
        return this.pubSubNoLocal;
    }

    /**
     * Configure the reply destination type. By default, the configured {@code pubSubDomain}
     * value is used (see {@link #isPubSubDomain()}.
     * <p>This setting primarily indicates what type of destination to resolve if dynamic
     * destinations are enabled.
     * @param replyPubSubDomain "true" for the Publish/Subscribe domain ({@link Topic Topics}),
     * "false" for the Point-to-Point domain ({@link Queue Queues})
     * @since 4.2
     * @see #setDestinationResolver
     */
    public void setReplyPubSubDomain(boolean replyPubSubDomain) {
        this.replyPubSubDomain = replyPubSubDomain;
    }

    /**
     * Return whether the Publish/Subscribe domain ({@link javax.jms.Topic Topics}) is used
     * for replies. Otherwise, the Point-to-Point domain ({@link javax.jms.Queue Queues})
     * is used.
     * @since 4.2
     */
    @Override
    public boolean isReplyPubSubDomain() {
        if (this.replyPubSubDomain != null) {
            return replyPubSubDomain;
        } else {
            return isPubSubDomain();
        }
    }

    /**
     * Set the {@link MessageConverter} strategy for converting JMS Messages.
     * @since 4.1
     */
    public void setMessageConverter(MessageConverter messageConverter) {
        this.messageConverter = messageConverter;
    }

    @Override
    public MessageConverter getMessageConverter() {
        return this.messageConverter;
    }

    /**
     * Set the JMS ExceptionListener to notify in case of a JMSException thrown
     * by the registered message listener or the invocation infrastructure.
     */
    public void setExceptionListener(ExceptionListener exceptionListener) {
        this.exceptionListener = exceptionListener;
    }

    /**
     * Return the JMS ExceptionListener to notify in case of a JMSException thrown
     * by the registered message listener or the invocation infrastructure, if any.
     */
    public ExceptionListener getExceptionListener() {
        return this.exceptionListener;
    }

    /**
     * Set the ErrorHandler to be invoked in case of any uncaught exceptions thrown
     * while processing a Message.
     * <p>By default, there will be <b>no</b> ErrorHandler so that error-level
     * logging is the only result.
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Return the ErrorHandler to be invoked in case of any uncaught exceptions thrown
     * while processing a Message.
     * @since 4.1
     */
    public ErrorHandler getErrorHandler() {
        return this.errorHandler;
    }

    /**
     * Set whether to expose the listener JMS Session to a registered
     * {@link SessionAwareMessageListener} as well as to
     * {@link org.springframework.jms.core.JmsTemplate} calls.
     * <p>Default is "true", reusing the listener's {@link Session}.
     * Turn this off to expose a fresh JMS Session fetched from the same
     * underlying JMS {@link Connection} instead, which might be necessary
     * on some JMS providers.
     * <p>Note that Sessions managed by an external transaction manager will
     * always get exposed to {@link org.springframework.jms.core.JmsTemplate}
     * calls. So in terms of JmsTemplate exposure, this setting only affects
     * locally transacted Sessions.
     * @see SessionAwareMessageListener
     */
    public void setExposeListenerSession(boolean exposeListenerSession) {
        this.exposeListenerSession = exposeListenerSession;
    }

    /**
     * Return whether to expose the listener JMS {@link Session} to a
     * registered {@link SessionAwareMessageListener}.
     */
    public boolean isExposeListenerSession() {
        return this.exposeListenerSession;
    }

    /**
     * Set whether to accept received messages while the listener container
     * in the process of stopping.
     * <p>Default is "false", rejecting such messages through aborting the
     * receive attempt. Switch this flag on to fully process such messages
     * even in the stopping phase, with the drawback that even newly sent
     * messages might still get processed (if coming in before all receive
     * timeouts have expired).
     * <p><b>NOTE:</b> Aborting receive attempts for such incoming messages
     * might lead to the provider's retry count decreasing for the affected
     * messages. If you have a high number of concurrent consumers, make sure
     * that the number of retries is higher than the number of consumers,
     * to be on the safe side for all potential stopping scenarios.
     */
    public void setAcceptMessagesWhileStopping(boolean acceptMessagesWhileStopping) {
        this.acceptMessagesWhileStopping = acceptMessagesWhileStopping;
    }

    /**
     * Return whether to accept received messages while the listener container
     * in the process of stopping.
     */
    public boolean isAcceptMessagesWhileStopping() {
        return this.acceptMessagesWhileStopping;
    }

    @Override
    protected void validateConfiguration() {
        if (this.destination == null) {
            throw new IllegalArgumentException("Property 'destination' or 'destinationName' is required");
        }
    }

    @Override
    public void setupMessageListener(Object messageListener) {
        setMessageListener(messageListener);
    }

    // -------------------------------------------------------------------------
    // Template methods for listener execution
    // -------------------------------------------------------------------------
    /**
     * Execute the specified listener,
     * committing or rolling back the transaction afterwards (if necessary).
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @see #invokeListener
     * @see #commitIfNecessary
     * @see #rollbackOnExceptionIfNecessary
     * @see #handleListenerException
     */
    protected void executeListener(Session session, Message message) {
        try {
            doExecuteListener(session, message);
        } catch (Throwable ex) {
            handleListenerException(ex);
        }
    }

    /**
     * Execute the specified listener,
     * committing or rolling back the transaction afterwards (if necessary).
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see #invokeListener
     * @see #commitIfNecessary
     * @see #rollbackOnExceptionIfNecessary
     * @see #convertJmsAccessException
     */
    protected void doExecuteListener(Session session, Message message) throws JMSException {
        if (!isAcceptMessagesWhileStopping() && !isRunning()) {
            if (logger.isWarnEnabled()) {
                logger.warn("Rejecting received message because of the listener container " + "having been stopped in the meantime: " + message);
            }
            rollbackIfNecessary(session);
            throw new MessageRejectedWhileStoppingException();
        }
        try {
            invokeListener(session, message);
        } catch (JMSException ex) {
            rollbackOnExceptionIfNecessary(session, ex);
            throw ex;
        } catch (RuntimeException ex) {
            rollbackOnExceptionIfNecessary(session, ex);
            throw ex;
        } catch (Error err) {
            rollbackOnExceptionIfNecessary(session, err);
            throw err;
        }
        commitIfNecessary(session, message);
    }

    /**
     * Invoke the specified listener: either as standard JMS MessageListener
     * or (preferably) as Spring SessionAwareMessageListener.
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see #setMessageListener
     */
    @SuppressWarnings("rawtypes")
    protected void invokeListener(Session session, Message message) throws JMSException {
        Object listener = getMessageListener();
        if (listener instanceof SessionAwareMessageListener) {
            doInvokeListener((SessionAwareMessageListener) listener, session, message);
        } else if (listener instanceof MessageListener) {
            doInvokeListener((MessageListener) listener, message);
        } else if (listener != null) {
            throw new IllegalArgumentException("Only MessageListener and SessionAwareMessageListener supported: " + listener);
        } else {
            throw new IllegalStateException("No message listener specified - see property 'messageListener'");
        }
    }

    /**
     * Invoke the specified listener as Spring SessionAwareMessageListener,
     * exposing a new JMS Session (potentially with its own transaction)
     * to the listener if demanded.
     * @param listener the Spring SessionAwareMessageListener to invoke
     * @param session the JMS Session to operate on
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see SessionAwareMessageListener
     * @see #setExposeListenerSession
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected void doInvokeListener(SessionAwareMessageListener listener, Session session, Message message) throws JMSException {
        Connection conToClose = null;
        Session sessionToClose = null;
        try {
            Session sessionToUse = session;
            if (!isExposeListenerSession()) {
                // We need to expose a separate Session.
                conToClose = createConnection();
                sessionToClose = createSession(conToClose);
                sessionToUse = sessionToClose;
            }
            // Actually invoke the message listener...
            listener.onMessage(message, sessionToUse);
            // Clean up specially exposed Session, if any.
            if (sessionToUse != session) {
                if (sessionToUse.getTransacted() && isSessionLocallyTransacted(sessionToUse)) {
                    // Transacted session created by this container -> commit.
                    JmsUtils.commitIfNecessary(sessionToUse);
                }
            }
        } finally {
            JmsUtils.closeSession(sessionToClose);
            JmsUtils.closeConnection(conToClose);
        }
    }

    /**
     * Invoke the specified listener as standard JMS MessageListener.
     * <p>Default implementation performs a plain invocation of the
     * {@code onMessage} method.
     * @param listener the JMS MessageListener to invoke
     * @param message the received JMS Message
     * @throws JMSException if thrown by JMS API methods
     * @see javax.jms.MessageListener#onMessage
     */
    protected void doInvokeListener(MessageListener listener, Message message) throws JMSException {
        listener.onMessage(message);
    }

    /**
     * Perform a commit or message acknowledgement, as appropriate.
     * @param session the JMS Session to commit
     * @param message the Message to acknowledge
     * @throws javax.jms.JMSException in case of commit failure
     */
    protected void commitIfNecessary(Session session, Message message) throws JMSException {
        // Commit session or acknowledge message.
        if (session.getTransacted()) {
            // Commit necessary - but avoid commit call within a JTA transaction.
            if (isSessionLocallyTransacted(session)) {
                // Transacted session created by this container -> commit.
                JmsUtils.commitIfNecessary(session);
            }
        } else if (message != null && isClientAcknowledge(session)) {
            message.acknowledge();
        }
    }

    /**
     * Perform a rollback, if appropriate.
     * @param session the JMS Session to rollback
     * @throws javax.jms.JMSException in case of a rollback error
     */
    protected void rollbackIfNecessary(Session session) throws JMSException {
        if (session.getTransacted()) {
            if (isSessionLocallyTransacted(session)) {
                // Transacted session created by this container -> rollback.
                JmsUtils.rollbackIfNecessary(session);
            }
        } else if (isClientAcknowledge(session)) {
            session.recover();
        }
    }

    /**
     * Perform a rollback, handling rollback exceptions properly.
     * @param session the JMS Session to rollback
     * @param ex the thrown application exception or error
     * @throws javax.jms.JMSException in case of a rollback error
     */
    protected void rollbackOnExceptionIfNecessary(Session session, Throwable ex) throws JMSException {
        try {
            if (session.getTransacted()) {
                if (isSessionLocallyTransacted(session)) {
                    // Transacted session created by this container -> rollback.
                    if (logger.isDebugEnabled()) {
                        logger.debug("Initiating transaction rollback on application exception", ex);
                    }
                    JmsUtils.rollbackIfNecessary(session);
                }
            } else if (isClientAcknowledge(session)) {
                session.recover();
            }
        } catch (IllegalStateException ex2) {
            logger.debug("Could not roll back because Session already closed", ex2);
        } catch (JMSException ex2) {
            logger.error("Application exception overridden by rollback exception", ex);
            throw ex2;
        } catch (RuntimeException ex2) {
            logger.error("Application exception overridden by rollback exception", ex);
            throw ex2;
        } catch (Error err) {
            logger.error("Application exception overridden by rollback error", ex);
            throw err;
        }
    }

    /**
     * Check whether the given Session is locally transacted, that is, whether
     * its transaction is managed by this listener container's Session handling
     * and not by an external transaction coordinator.
     * <p>Note: The Session's own transacted flag will already have been checked
     * before. This method is about finding out whether the Session's transaction
     * is local or externally coordinated.
     * @param session the Session to check
     * @return whether the given Session is locally transacted
     * @see #isSessionTransacted()
     * @see org.springframework.jms.connection.ConnectionFactoryUtils#isSessionTransactional
     */
    protected boolean isSessionLocallyTransacted(Session session) {
        return isSessionTransacted();
    }

    /**
     * Create a JMS MessageConsumer for the given Session and Destination.
     * <p>This implementation uses JMS 1.1 API.
     * @param session the JMS Session to create a MessageConsumer for
     * @param destination the JMS Destination to create a MessageConsumer for
     * @return the new JMS MessageConsumer
     * @throws javax.jms.JMSException if thrown by JMS API methods
     */
    protected MessageConsumer createConsumer(Session session, Destination destination) throws JMSException {
        if (isPubSubDomain() && destination instanceof Topic) {
            if (isSubscriptionShared()) {
                // createSharedConsumer((Topic) dest, subscription, selector);
                // createSharedDurableConsumer((Topic) dest, subscription, selector);
                Method method = (isSubscriptionDurable() ? createSharedDurableConsumerMethod : createSharedConsumerMethod);
                try {
                    return (MessageConsumer) method.invoke(session, destination, getSubscriptionName(), getMessageSelector());
                } catch (InvocationTargetException ex) {
                    if (ex.getTargetException() instanceof JMSException) {
                        throw (JMSException) ex.getTargetException();
                    }
                    ReflectionUtils.handleInvocationTargetException(ex);
                    return null;
                } catch (IllegalAccessException ex) {
                    throw new IllegalStateException("Could not access JMS 2.0 API method: " + ex.getMessage());
                }
            } else if (isSubscriptionDurable()) {
                return session.createDurableSubscriber((Topic) destination, getSubscriptionName(), getMessageSelector(), isPubSubNoLocal());
            } else {
                // Only preplaced in the NoLocal flag in case of a Topic (pub-sub mode):
                // Some JMS providers, such as WebSphere MQ 6.0, throw IllegalStateException
                // in case of the NoLocal flag being specified for a Queue.
                return session.createConsumer(destination, getMessageSelector(), isPubSubNoLocal());
            }
        } else {
            return session.createConsumer(destination, getMessageSelector());
        }
    }

    /**
     * Handle the given exception that arose during listener execution.
     * <p>The default implementation logs the exception at warn level,
     * not propagating it to the JMS provider — replaceduming that all handling of
     * acknowledgement and/or transactions is done by this listener container.
     * This can be overridden in subclreplacedes.
     * @param ex the exception to handle
     */
    protected void handleListenerException(Throwable ex) {
        if (ex instanceof MessageRejectedWhileStoppingException) {
            // Internal exception - has been handled before.
            return;
        }
        if (ex instanceof JMSException) {
            invokeExceptionListener((JMSException) ex);
        }
        if (isActive()) {
            // Regular case: failed while active.
            // Invoke ErrorHandler if available.
            invokeErrorHandler(ex);
        } else {
            // Rare case: listener thread failed after container shutdown.
            // Log at debug level, to avoid spamming the shutdown log.
            logger.debug("Listener exception after container shutdown", ex);
        }
    }

    /**
     * Invoke the registered JMS ExceptionListener, if any.
     * @param ex the exception that arose during JMS processing
     * @see #setExceptionListener
     */
    protected void invokeExceptionListener(JMSException ex) {
        ExceptionListener exceptionListener = getExceptionListener();
        if (exceptionListener != null) {
            exceptionListener.onException(ex);
        }
    }

    /**
     * Invoke the registered ErrorHandler, if any. Log at warn level otherwise.
     * @param ex the uncaught error that arose during JMS processing.
     * @see #setErrorHandler
     */
    protected void invokeErrorHandler(Throwable ex) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            errorHandler.handleError(ex);
        } else {
            logger.warn("Execution of JMS message listener failed, and no ErrorHandler has been set.", ex);
        }
    }

    /**
     * Internal exception clreplaced that indicates a rejected message on shutdown.
     * Used to trigger a rollback for an external transaction manager in that case.
     */
    @SuppressWarnings("serial")
    private static clreplaced MessageRejectedWhileStoppingException extends RuntimeException {
    }
}

19 View Source File : AbstractMessageListenerContainer.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Set the ErrorHandler to be invoked in case of any uncaught exceptions thrown
 * while processing a Message.
 * <p>By default, there will be <b>no</b> ErrorHandler so that error-level
 * logging is the only result.
 */
public void setErrorHandler(ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

19 View Source File : AbstractJmsListenerContainerFactory.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Base {@link JmsListenerContainerFactory} for Spring's base container implementation.
 *
 * @author Stephane Nicoll
 * @since 4.1
 * @see AbstractMessageListenerContainer
 */
public abstract clreplaced AbstractJmsListenerContainerFactory<C extends AbstractMessageListenerContainer> implements JmsListenerContainerFactory<C> {

    protected final Log logger = LogFactory.getLog(getClreplaced());

    private ConnectionFactory connectionFactory;

    private DestinationResolver destinationResolver;

    private ErrorHandler errorHandler;

    private MessageConverter messageConverter;

    private Boolean sessionTransacted;

    private Integer sessionAcknowledgeMode;

    private Boolean pubSubDomain;

    private Boolean replyPubSubDomain;

    private Boolean subscriptionDurable;

    private Boolean subscriptionShared;

    private String clientId;

    private Integer phase;

    private Boolean autoStartup;

    /**
     * @see AbstractMessageListenerContainer#setConnectionFactory(ConnectionFactory)
     */
    public void setConnectionFactory(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    /**
     * @see AbstractMessageListenerContainer#setDestinationResolver(DestinationResolver)
     */
    public void setDestinationResolver(DestinationResolver destinationResolver) {
        this.destinationResolver = destinationResolver;
    }

    /**
     * @see AbstractMessageListenerContainer#setErrorHandler(ErrorHandler)
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * @see AbstractMessageListenerContainer#setMessageConverter(MessageConverter)
     */
    public void setMessageConverter(MessageConverter messageConverter) {
        this.messageConverter = messageConverter;
    }

    /**
     * @see AbstractMessageListenerContainer#setSessionTransacted(boolean)
     */
    public void setSessionTransacted(Boolean sessionTransacted) {
        this.sessionTransacted = sessionTransacted;
    }

    /**
     * @see AbstractMessageListenerContainer#setSessionAcknowledgeMode(int)
     */
    public void setSessionAcknowledgeMode(Integer sessionAcknowledgeMode) {
        this.sessionAcknowledgeMode = sessionAcknowledgeMode;
    }

    /**
     * @see AbstractMessageListenerContainer#setPubSubDomain(boolean)
     */
    public void setPubSubDomain(Boolean pubSubDomain) {
        this.pubSubDomain = pubSubDomain;
    }

    /**
     * @see AbstractMessageListenerContainer#setReplyPubSubDomain(boolean)
     */
    public void setReplyPubSubDomain(Boolean replyPubSubDomain) {
        this.replyPubSubDomain = replyPubSubDomain;
    }

    /**
     * @see AbstractMessageListenerContainer#setSubscriptionDurable(boolean)
     */
    public void setSubscriptionDurable(Boolean subscriptionDurable) {
        this.subscriptionDurable = subscriptionDurable;
    }

    /**
     * @see AbstractMessageListenerContainer#setSubscriptionShared(boolean)
     */
    public void setSubscriptionShared(Boolean subscriptionShared) {
        this.subscriptionShared = subscriptionShared;
    }

    /**
     * @see AbstractMessageListenerContainer#setClientId(String)
     */
    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    /**
     * @see AbstractMessageListenerContainer#setPhase(int)
     */
    public void setPhase(int phase) {
        this.phase = phase;
    }

    /**
     * @see AbstractMessageListenerContainer#setAutoStartup(boolean)
     */
    public void setAutoStartup(boolean autoStartup) {
        this.autoStartup = autoStartup;
    }

    @Override
    public C createListenerContainer(JmsListenerEndpoint endpoint) {
        C instance = createContainerInstance();
        if (this.connectionFactory != null) {
            instance.setConnectionFactory(this.connectionFactory);
        }
        if (this.destinationResolver != null) {
            instance.setDestinationResolver(this.destinationResolver);
        }
        if (this.errorHandler != null) {
            instance.setErrorHandler(this.errorHandler);
        }
        if (this.messageConverter != null) {
            instance.setMessageConverter(this.messageConverter);
        }
        if (this.sessionTransacted != null) {
            instance.setSessionTransacted(this.sessionTransacted);
        }
        if (this.sessionAcknowledgeMode != null) {
            instance.setSessionAcknowledgeMode(this.sessionAcknowledgeMode);
        }
        if (this.pubSubDomain != null) {
            instance.setPubSubDomain(this.pubSubDomain);
        }
        if (this.replyPubSubDomain != null) {
            instance.setReplyPubSubDomain(this.replyPubSubDomain);
        }
        if (this.subscriptionDurable != null) {
            instance.setSubscriptionDurable(this.subscriptionDurable);
        }
        if (this.subscriptionShared != null) {
            instance.setSubscriptionShared(this.subscriptionShared);
        }
        if (this.clientId != null) {
            instance.setClientId(this.clientId);
        }
        if (this.phase != null) {
            instance.setPhase(this.phase);
        }
        if (this.autoStartup != null) {
            instance.setAutoStartup(this.autoStartup);
        }
        endpoint.setupListenerContainer(instance);
        initializeContainer(instance);
        return instance;
    }

    /**
     * Create an empty container instance.
     */
    protected abstract C createContainerInstance();

    /**
     * Further initialize the specified container.
     * <p>Subclreplacedes can inherit from this method to apply extra
     * configuration if necessary.
     */
    protected void initializeContainer(C instance) {
    }
}

19 View Source File : TimerManagerTaskScheduler.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Implementation of Spring's {@link TaskScheduler} interface, wrapping
 * a CommonJ {@link commonj.timers.TimerManager}.
 *
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @since 3.0
 */
public clreplaced TimerManagerTaskScheduler extends TimerManagerAccessor implements TaskScheduler {

    private volatile ErrorHandler errorHandler;

    /**
     * Provide an {@link ErrorHandler} strategy.
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    @Override
    public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
        return new ReschedulingTimerListener(errorHandlingTask(task, true), trigger).schedule();
    }

    @Override
    public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
        TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, false));
        Timer timer = getTimerManager().schedule(futureTask, startTime);
        futureTask.setTimer(timer);
        return futureTask;
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
        TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
        Timer timer = getTimerManager().scheduleAtFixedRate(futureTask, startTime, period);
        futureTask.setTimer(timer);
        return futureTask;
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
        TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
        Timer timer = getTimerManager().scheduleAtFixedRate(futureTask, 0, period);
        futureTask.setTimer(timer);
        return futureTask;
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
        TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
        Timer timer = getTimerManager().schedule(futureTask, startTime, delay);
        futureTask.setTimer(timer);
        return futureTask;
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
        TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
        Timer timer = getTimerManager().schedule(futureTask, 0, delay);
        futureTask.setTimer(timer);
        return futureTask;
    }

    private Runnable errorHandlingTask(Runnable delegate, boolean isRepeatingTask) {
        return TaskUtils.decorateTaskWithErrorHandler(delegate, this.errorHandler, isRepeatingTask);
    }

    /**
     * ScheduledFuture adapter that wraps a CommonJ Timer.
     */
    private static clreplaced TimerScheduledFuture extends FutureTask<Object> implements TimerListener, ScheduledFuture<Object> {

        protected transient Timer timer;

        protected transient boolean cancelled = false;

        public TimerScheduledFuture(Runnable runnable) {
            super(runnable, null);
        }

        public void setTimer(Timer timer) {
            this.timer = timer;
        }

        @Override
        public void timerExpired(Timer timer) {
            runAndReset();
        }

        @Override
        public boolean cancel(boolean mayInterruptIfRunning) {
            boolean result = super.cancel(mayInterruptIfRunning);
            this.timer.cancel();
            this.cancelled = true;
            return result;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(System.currentTimeMillis() - this.timer.getScheduledExecutionTime(), TimeUnit.MILLISECONDS);
        }

        @Override
        public int compareTo(Delayed other) {
            if (this == other) {
                return 0;
            }
            long diff = getDelay(TimeUnit.MILLISECONDS) - other.getDelay(TimeUnit.MILLISECONDS);
            return (diff == 0 ? 0 : ((diff < 0) ? -1 : 1));
        }
    }

    /**
     * ScheduledFuture adapter for trigger-based rescheduling.
     */
    private clreplaced ReschedulingTimerListener extends TimerScheduledFuture {

        private final Trigger trigger;

        private final SimpleTriggerContext triggerContext = new SimpleTriggerContext();

        private volatile Date scheduledExecutionTime;

        public ReschedulingTimerListener(Runnable runnable, Trigger trigger) {
            super(runnable);
            this.trigger = trigger;
        }

        public ScheduledFuture<?> schedule() {
            this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
            if (this.scheduledExecutionTime == null) {
                return null;
            }
            setTimer(getTimerManager().schedule(this, this.scheduledExecutionTime));
            return this;
        }

        @Override
        public void timerExpired(Timer timer) {
            Date actualExecutionTime = new Date();
            super.timerExpired(timer);
            Date completionTime = new Date();
            this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
            if (!this.cancelled) {
                schedule();
            }
        }
    }
}

19 View Source File : TaskUtils.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Utility methods for decorating tasks with error handling.
 *
 * <p><b>NOTE:</b> This clreplaced is intended for internal use by Spring's scheduler
 * implementations. It is only public so that it may be accessed from impl clreplacedes
 * within other packages. It is <i>not</i> intended for general use.
 *
 * @author Mark Fisher
 * @author Juergen Hoeller
 * @since 3.0
 */
public abstract clreplaced TaskUtils {

    /**
     * An ErrorHandler strategy that will log the Exception but perform
     * no further handling. This will suppress the error so that
     * subsequent executions of the task will not be prevented.
     */
    public static final ErrorHandler LOG_AND_SUPPRESS_ERROR_HANDLER = new LoggingErrorHandler();

    /**
     * An ErrorHandler strategy that will log at error level and then
     * re-throw the Exception. Note: this will typically prevent subsequent
     * execution of a scheduled task.
     */
    public static final ErrorHandler LOG_AND_PROPAGATE_ERROR_HANDLER = new PropagatingErrorHandler();

    /**
     * Decorate the task for error handling. If the provided {@link ErrorHandler}
     * is not {@code null}, it will be used. Otherwise, repeating tasks will have
     * errors suppressed by default whereas one-shot tasks will have errors
     * propagated by default since those errors may be expected through the
     * returned {@link Future}. In both cases, the errors will be logged.
     */
    public static DelegatingErrorHandlingRunnable decorateTaskWithErrorHandler(Runnable task, ErrorHandler errorHandler, boolean isRepeatingTask) {
        if (task instanceof DelegatingErrorHandlingRunnable) {
            return (DelegatingErrorHandlingRunnable) task;
        }
        ErrorHandler eh = (errorHandler != null ? errorHandler : getDefaultErrorHandler(isRepeatingTask));
        return new DelegatingErrorHandlingRunnable(task, eh);
    }

    /**
     * Return the default {@link ErrorHandler} implementation based on the boolean
     * value indicating whether the task will be repeating or not. For repeating tasks
     * it will suppress errors, but for one-time tasks it will propagate. In both
     * cases, the error will be logged.
     */
    public static ErrorHandler getDefaultErrorHandler(boolean isRepeatingTask) {
        return (isRepeatingTask ? LOG_AND_SUPPRESS_ERROR_HANDLER : LOG_AND_PROPAGATE_ERROR_HANDLER);
    }

    /**
     * An {@link ErrorHandler} implementation that logs the Throwable at error
     * level. It does not perform any additional error handling. This can be
     * useful when suppression of errors is the intended behavior.
     */
    private static clreplaced LoggingErrorHandler implements ErrorHandler {

        private final Log logger = LogFactory.getLog(LoggingErrorHandler.clreplaced);

        @Override
        public void handleError(Throwable t) {
            if (logger.isErrorEnabled()) {
                logger.error("Unexpected error occurred in scheduled task.", t);
            }
        }
    }

    /**
     * An {@link ErrorHandler} implementation that logs the Throwable at error
     * level and then propagates it.
     */
    private static clreplaced PropagatingErrorHandler extends LoggingErrorHandler {

        @Override
        public void handleError(Throwable t) {
            super.handleError(t);
            ReflectionUtils.rethrowRuntimeException(t);
        }
    }
}

19 View Source File : TaskUtils.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Decorate the task for error handling. If the provided {@link ErrorHandler}
 * is not {@code null}, it will be used. Otherwise, repeating tasks will have
 * errors suppressed by default whereas one-shot tasks will have errors
 * propagated by default since those errors may be expected through the
 * returned {@link Future}. In both cases, the errors will be logged.
 */
public static DelegatingErrorHandlingRunnable decorateTaskWithErrorHandler(Runnable task, ErrorHandler errorHandler, boolean isRepeatingTask) {
    if (task instanceof DelegatingErrorHandlingRunnable) {
        return (DelegatingErrorHandlingRunnable) task;
    }
    ErrorHandler eh = (errorHandler != null ? errorHandler : getDefaultErrorHandler(isRepeatingTask));
    return new DelegatingErrorHandlingRunnable(task, eh);
}

19 View Source File : ThreadPoolTaskScheduler.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Implementation of Spring's {@link TaskScheduler} interface, wrapping
 * a native {@link java.util.concurrent.ScheduledThreadPoolExecutor}.
 *
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @since 3.0
 * @see #setPoolSize
 * @see #setRemoveOnCancelPolicy
 * @see #setThreadFactory
 * @see #setErrorHandler
 */
@SuppressWarnings("serial")
public clreplaced ThreadPoolTaskScheduler extends ExecutorConfigurationSupport implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler {

    // ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 7+
    private static final boolean setRemoveOnCancelPolicyAvailable = ClreplacedUtils.hasMethod(ScheduledThreadPoolExecutor.clreplaced, "setRemoveOnCancelPolicy", boolean.clreplaced);

    private volatile int poolSize = 1;

    private volatile boolean removeOnCancelPolicy = false;

    private volatile ScheduledExecutorService scheduledExecutor;

    private volatile ErrorHandler errorHandler;

    /**
     * Set the ScheduledExecutorService's pool size.
     * Default is 1.
     * <p><b>This setting can be modified at runtime, for example through JMX.</b>
     */
    public void setPoolSize(int poolSize) {
        replacedert.isTrue(poolSize > 0, "'poolSize' must be 1 or higher");
        this.poolSize = poolSize;
        if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
            ((ScheduledThreadPoolExecutor) this.scheduledExecutor).setCorePoolSize(poolSize);
        }
    }

    /**
     * Set the remove-on-cancel mode on {@link ScheduledThreadPoolExecutor} (JDK 7+).
     * <p>Default is {@code false}. If set to {@code true}, the target executor will be
     * switched into remove-on-cancel mode (if possible, with a soft fallback otherwise).
     * <p><b>This setting can be modified at runtime, for example through JMX.</b>
     */
    @UsesJava7
    public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) {
        this.removeOnCancelPolicy = removeOnCancelPolicy;
        if (setRemoveOnCancelPolicyAvailable && this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
            ((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(removeOnCancelPolicy);
        } else if (removeOnCancelPolicy && this.scheduledExecutor != null) {
            logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor");
        }
    }

    /**
     * Set a custom {@link ErrorHandler} strategy.
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    @UsesJava7
    @Override
    protected ExecutorService initializeExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
        this.scheduledExecutor = createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler);
        if (this.removeOnCancelPolicy) {
            if (setRemoveOnCancelPolicyAvailable && this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
                ((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(true);
            } else {
                logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor");
            }
        }
        return this.scheduledExecutor;
    }

    /**
     * Create a new {@link ScheduledExecutorService} instance.
     * <p>The default implementation creates a {@link ScheduledThreadPoolExecutor}.
     * Can be overridden in subclreplacedes to provide custom {@link ScheduledExecutorService} instances.
     * @param poolSize the specified pool size
     * @param threadFactory the ThreadFactory to use
     * @param rejectedExecutionHandler the RejectedExecutionHandler to use
     * @return a new ScheduledExecutorService instance
     * @see #afterPropertiesSet()
     * @see java.util.concurrent.ScheduledThreadPoolExecutor
     */
    protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
        return new ScheduledThreadPoolExecutor(poolSize, threadFactory, rejectedExecutionHandler);
    }

    /**
     * Return the underlying ScheduledExecutorService for native access.
     * @return the underlying ScheduledExecutorService (never {@code null})
     * @throws IllegalStateException if the ThreadPoolTaskScheduler hasn't been initialized yet
     */
    public ScheduledExecutorService getScheduledExecutor() throws IllegalStateException {
        replacedert.state(this.scheduledExecutor != null, "ThreadPoolTaskScheduler not initialized");
        return this.scheduledExecutor;
    }

    /**
     * Return the underlying ScheduledThreadPoolExecutor, if available.
     * @return the underlying ScheduledExecutorService (never {@code null})
     * @throws IllegalStateException if the ThreadPoolTaskScheduler hasn't been initialized yet
     * or if the underlying ScheduledExecutorService isn't a ScheduledThreadPoolExecutor
     * @see #getScheduledExecutor()
     */
    public ScheduledThreadPoolExecutor getScheduledThreadPoolExecutor() throws IllegalStateException {
        replacedert.state(this.scheduledExecutor instanceof ScheduledThreadPoolExecutor, "No ScheduledThreadPoolExecutor available");
        return (ScheduledThreadPoolExecutor) this.scheduledExecutor;
    }

    /**
     * Return the current pool size.
     * <p>Requires an underlying {@link ScheduledThreadPoolExecutor}.
     * @see #getScheduledThreadPoolExecutor()
     * @see java.util.concurrent.ScheduledThreadPoolExecutor#getPoolSize()
     */
    public int getPoolSize() {
        if (this.scheduledExecutor == null) {
            // Not initialized yet: replacedume initial pool size.
            return this.poolSize;
        }
        return getScheduledThreadPoolExecutor().getPoolSize();
    }

    /**
     * Return the current setting for the remove-on-cancel mode.
     * <p>Requires an underlying {@link ScheduledThreadPoolExecutor}.
     */
    @UsesJava7
    public boolean isRemoveOnCancelPolicy() {
        if (!setRemoveOnCancelPolicyAvailable) {
            return false;
        }
        if (this.scheduledExecutor == null) {
            // Not initialized yet: return our setting for the time being.
            return this.removeOnCancelPolicy;
        }
        return getScheduledThreadPoolExecutor().getRemoveOnCancelPolicy();
    }

    /**
     * Return the number of currently active threads.
     * <p>Requires an underlying {@link ScheduledThreadPoolExecutor}.
     * @see #getScheduledThreadPoolExecutor()
     * @see java.util.concurrent.ScheduledThreadPoolExecutor#getActiveCount()
     */
    public int getActiveCount() {
        if (this.scheduledExecutor == null) {
            // Not initialized yet: replacedume no active threads.
            return 0;
        }
        return getScheduledThreadPoolExecutor().getActiveCount();
    }

    // SchedulingTaskExecutor implementation
    @Override
    public void execute(Runnable task) {
        Executor executor = getScheduledExecutor();
        try {
            executor.execute(errorHandlingTask(task, false));
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public void execute(Runnable task, long startTimeout) {
        execute(task);
    }

    @Override
    public Future<?> submit(Runnable task) {
        ExecutorService executor = getScheduledExecutor();
        try {
            return executor.submit(errorHandlingTask(task, false));
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        ExecutorService executor = getScheduledExecutor();
        try {
            Callable<T> taskToUse = task;
            if (this.errorHandler != null) {
                taskToUse = new DelegatingErrorHandlingCallable<T>(task, this.errorHandler);
            }
            return executor.submit(taskToUse);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ListenableFuture<?> submitListenable(Runnable task) {
        ExecutorService executor = getScheduledExecutor();
        try {
            ListenableFutureTask<Object> future = new ListenableFutureTask<Object>(task, null);
            executor.execute(errorHandlingTask(future, false));
            return future;
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
        ExecutorService executor = getScheduledExecutor();
        try {
            ListenableFutureTask<T> future = new ListenableFutureTask<T>(task);
            executor.execute(errorHandlingTask(future, false));
            return future;
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public boolean prefersShortLivedTasks() {
        return true;
    }

    // TaskScheduler implementation
    @Override
    public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
        ScheduledExecutorService executor = getScheduledExecutor();
        try {
            ErrorHandler errorHandler = (this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
            return new ReschedulingRunnable(task, trigger, executor, errorHandler).schedule();
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
        ScheduledExecutorService executor = getScheduledExecutor();
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return executor.schedule(errorHandlingTask(task, false), initialDelay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
        ScheduledExecutorService executor = getScheduledExecutor();
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return executor.scheduleAtFixedRate(errorHandlingTask(task, true), initialDelay, period, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
        ScheduledExecutorService executor = getScheduledExecutor();
        try {
            return executor.scheduleAtFixedRate(errorHandlingTask(task, true), 0, period, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
        ScheduledExecutorService executor = getScheduledExecutor();
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), initialDelay, delay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
        ScheduledExecutorService executor = getScheduledExecutor();
        try {
            return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), 0, delay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
        }
    }

    private Runnable errorHandlingTask(Runnable task, boolean isRepeatingTask) {
        return TaskUtils.decorateTaskWithErrorHandler(task, this.errorHandler, isRepeatingTask);
    }

    private static clreplaced DelegatingErrorHandlingCallable<V> implements Callable<V> {

        private final Callable<V> delegate;

        private final ErrorHandler errorHandler;

        public DelegatingErrorHandlingCallable(Callable<V> delegate, ErrorHandler errorHandler) {
            this.delegate = delegate;
            this.errorHandler = errorHandler;
        }

        @Override
        public V call() throws Exception {
            try {
                return this.delegate.call();
            } catch (Throwable t) {
                this.errorHandler.handleError(t);
                return null;
            }
        }
    }
}

19 View Source File : ConcurrentTaskScheduler.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Adapter that takes a {@code java.util.concurrent.ScheduledExecutorService} and
 * exposes a Spring {@link org.springframework.scheduling.TaskScheduler} for it.
 * Extends {@link ConcurrentTaskExecutor} in order to implement the
 * {@link org.springframework.scheduling.SchedulingTaskExecutor} interface as well.
 *
 * <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
 * in order to use it for trigger-based scheduling if possible, instead of Spring's
 * local trigger management which ends up delegating to regular delay-based scheduling
 * against the {@code java.util.concurrent.ScheduledExecutorService} API. For JSR-236 style
 * lookup in a Java EE 7 environment, consider using {@link DefaultManagedTaskScheduler}.
 *
 * <p>Note that there is a pre-built {@link ThreadPoolTaskScheduler} that allows for
 * defining a {@link java.util.concurrent.ScheduledThreadPoolExecutor} in bean style,
 * exposing it as a Spring {@link org.springframework.scheduling.TaskScheduler} directly.
 * This is a convenient alternative to a raw ScheduledThreadPoolExecutor definition with
 * a separate definition of the present adapter clreplaced.
 *
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @since 3.0
 * @see java.util.concurrent.ScheduledExecutorService
 * @see java.util.concurrent.ScheduledThreadPoolExecutor
 * @see java.util.concurrent.Executors
 * @see DefaultManagedTaskScheduler
 * @see ThreadPoolTaskScheduler
 */
public clreplaced ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements TaskScheduler {

    private static Clreplaced<?> managedScheduledExecutorServiceClreplaced;

    static {
        try {
            managedScheduledExecutorServiceClreplaced = ClreplacedUtils.forName("javax.enterprise.concurrent.ManagedScheduledExecutorService", ConcurrentTaskScheduler.clreplaced.getClreplacedLoader());
        } catch (ClreplacedNotFoundException ex) {
            // JSR-236 API not available...
            managedScheduledExecutorServiceClreplaced = null;
        }
    }

    private ScheduledExecutorService scheduledExecutor;

    private boolean enterpriseConcurrentScheduler = false;

    private ErrorHandler errorHandler;

    /**
     * Create a new ConcurrentTaskScheduler,
     * using a single thread executor as default.
     * @see java.util.concurrent.Executors#newSingleThreadScheduledExecutor()
     */
    public ConcurrentTaskScheduler() {
        super();
        setScheduledExecutor(null);
    }

    /**
     * Create a new ConcurrentTaskScheduler, using the given
     * {@link java.util.concurrent.ScheduledExecutorService} as shared delegate.
     * <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
     * in order to use it for trigger-based scheduling if possible,
     * instead of Spring's local trigger management.
     * @param scheduledExecutor the {@link java.util.concurrent.ScheduledExecutorService}
     * to delegate to for {@link org.springframework.scheduling.SchedulingTaskExecutor}
     * as well as {@link TaskScheduler} invocations
     */
    public ConcurrentTaskScheduler(ScheduledExecutorService scheduledExecutor) {
        super(scheduledExecutor);
        setScheduledExecutor(scheduledExecutor);
    }

    /**
     * Create a new ConcurrentTaskScheduler, using the given {@link java.util.concurrent.Executor}
     * and {@link java.util.concurrent.ScheduledExecutorService} as delegates.
     * <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
     * in order to use it for trigger-based scheduling if possible,
     * instead of Spring's local trigger management.
     * @param concurrentExecutor the {@link java.util.concurrent.Executor} to delegate to
     * for {@link org.springframework.scheduling.SchedulingTaskExecutor} invocations
     * @param scheduledExecutor the {@link java.util.concurrent.ScheduledExecutorService}
     * to delegate to for {@link TaskScheduler} invocations
     */
    public ConcurrentTaskScheduler(Executor concurrentExecutor, ScheduledExecutorService scheduledExecutor) {
        super(concurrentExecutor);
        setScheduledExecutor(scheduledExecutor);
    }

    /**
     * Specify the {@link java.util.concurrent.ScheduledExecutorService} to delegate to.
     * <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
     * in order to use it for trigger-based scheduling if possible,
     * instead of Spring's local trigger management.
     * <p>Note: This will only apply to {@link TaskScheduler} invocations.
     * If you want the given executor to apply to
     * {@link org.springframework.scheduling.SchedulingTaskExecutor} invocations
     * as well, preplaced the same executor reference to {@link #setConcurrentExecutor}.
     * @see #setConcurrentExecutor
     */
    public final void setScheduledExecutor(ScheduledExecutorService scheduledExecutor) {
        if (scheduledExecutor != null) {
            this.scheduledExecutor = scheduledExecutor;
            this.enterpriseConcurrentScheduler = (managedScheduledExecutorServiceClreplaced != null && managedScheduledExecutorServiceClreplaced.isInstance(scheduledExecutor));
        } else {
            this.scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
            this.enterpriseConcurrentScheduler = false;
        }
    }

    /**
     * Provide an {@link ErrorHandler} strategy.
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        replacedert.notNull(errorHandler, "'errorHandler' must not be null");
        this.errorHandler = errorHandler;
    }

    @Override
    public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
        try {
            if (this.enterpriseConcurrentScheduler) {
                return new EnterpriseConcurrentTriggerScheduler().schedule(decorateTask(task, true), trigger);
            } else {
                ErrorHandler errorHandler = (this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
                return new ReschedulingRunnable(task, trigger, this.scheduledExecutor, errorHandler).schedule();
            }
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return this.scheduledExecutor.schedule(decorateTask(task, false), initialDelay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return this.scheduledExecutor.scheduleAtFixedRate(decorateTask(task, true), initialDelay, period, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
        try {
            return this.scheduledExecutor.scheduleAtFixedRate(decorateTask(task, true), 0, period, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
        long initialDelay = startTime.getTime() - System.currentTimeMillis();
        try {
            return this.scheduledExecutor.scheduleWithFixedDelay(decorateTask(task, true), initialDelay, delay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
        try {
            return this.scheduledExecutor.scheduleWithFixedDelay(decorateTask(task, true), 0, delay, TimeUnit.MILLISECONDS);
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }

    private Runnable decorateTask(Runnable task, boolean isRepeatingTask) {
        Runnable result = TaskUtils.decorateTaskWithErrorHandler(task, this.errorHandler, isRepeatingTask);
        if (this.enterpriseConcurrentScheduler) {
            result = ManagedTaskBuilder.buildManagedTask(result, task.toString());
        }
        return result;
    }

    /**
     * Delegate that adapts a Spring Trigger to a JSR-236 Trigger.
     * Separated into an inner clreplaced in order to avoid a hard dependency on the JSR-236 API.
     */
    private clreplaced EnterpriseConcurrentTriggerScheduler {

        public ScheduledFuture<?> schedule(Runnable task, final Trigger trigger) {
            ManagedScheduledExecutorService executor = (ManagedScheduledExecutorService) scheduledExecutor;
            return executor.schedule(task, new javax.enterprise.concurrent.Trigger() {

                @Override
                public Date getNextRunTime(LastExecution le, Date taskScheduledTime) {
                    return trigger.nextExecutionTime(le != null ? new SimpleTriggerContext(le.getScheduledStart(), le.getRunStart(), le.getRunEnd()) : new SimpleTriggerContext());
                }

                @Override
                public boolean skipRun(LastExecution lastExecution, Date scheduledRunTime) {
                    return false;
                }
            });
        }
    }
}

19 View Source File : ConcurrentTaskScheduler.java
License : Apache License 2.0
Project Creator : langtianya

@Override
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
    try {
        if (this.enterpriseConcurrentScheduler) {
            return new EnterpriseConcurrentTriggerScheduler().schedule(decorateTask(task, true), trigger);
        } else {
            ErrorHandler errorHandler = (this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
            return new ReschedulingRunnable(task, trigger, this.scheduledExecutor, errorHandler).schedule();
        }
    } catch (RejectedExecutionException ex) {
        throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
    }
}

19 View Source File : ConcurrentTaskScheduler.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Provide an {@link ErrorHandler} strategy.
 */
public void setErrorHandler(ErrorHandler errorHandler) {
    replacedert.notNull(errorHandler, "'errorHandler' must not be null");
    this.errorHandler = errorHandler;
}

19 View Source File : SimpleApplicationEventMulticaster.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Simple implementation of the {@link ApplicationEventMulticaster} interface.
 *
 * <p>Multicasts all events to all registered listeners, leaving it up to
 * the listeners to ignore events that they are not interested in.
 * Listeners will usually perform corresponding {@code instanceof}
 * checks on the preplaceded-in event object.
 *
 * <p>By default, all listeners are invoked in the calling thread.
 * This allows the danger of a rogue listener blocking the entire application,
 * but adds minimal overhead. Specify an alternative task executor to have
 * listeners executed in different threads, for example from a thread pool.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Stephane Nicoll
 * @see #setTaskExecutor
 */
public clreplaced SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

    private Executor taskExecutor;

    private ErrorHandler errorHandler;

    /**
     * Create a new SimpleApplicationEventMulticaster.
     */
    public SimpleApplicationEventMulticaster() {
    }

    /**
     * Create a new SimpleApplicationEventMulticaster for the given BeanFactory.
     */
    public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
        setBeanFactory(beanFactory);
    }

    /**
     * Set a custom executor (typically a {@link org.springframework.core.task.TaskExecutor})
     * to invoke each listener with.
     * <p>Default is equivalent to {@link org.springframework.core.task.SyncTaskExecutor},
     * executing all listeners synchronously in the calling thread.
     * <p>Consider specifying an asynchronous task executor here to not block the
     * caller until all listeners have been executed. However, note that asynchronous
     * execution will not participate in the caller's thread context (clreplaced loader,
     * transaction replacedociation) unless the TaskExecutor explicitly supports this.
     * @see org.springframework.core.task.SyncTaskExecutor
     * @see org.springframework.core.task.SimpleAsyncTaskExecutor
     */
    public void setTaskExecutor(Executor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * Return the current task executor for this multicaster.
     */
    protected Executor getTaskExecutor() {
        return this.taskExecutor;
    }

    /**
     * Set the {@link ErrorHandler} to invoke in case an exception is thrown
     * from a listener.
     * <p>Default is none, with a listener exception stopping the current
     * multicast and getting propagated to the publisher of the current event.
     * If a {@linkplain #setTaskExecutor task executor} is specified, each
     * individual listener exception will get propagated to the executor but
     * won't necessarily stop execution of other listeners.
     * <p>Consider setting an {@link ErrorHandler} implementation that catches
     * and logs exceptions (a la
     * {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_SUPPRESS_ERROR_HANDLER})
     * or an implementation that logs exceptions while nevertheless propagating them
     * (e.g. {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_PROPAGATE_ERROR_HANDLER}).
     * @since 4.1
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Return the current error handler for this multicaster.
     * @since 4.1
     */
    protected ErrorHandler getErrorHandler() {
        return this.errorHandler;
    }

    @Override
    public void multicastEvent(ApplicationEvent event) {
        multicastEvent(event, resolveDefaultEventType(event));
    }

    @Override
    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {

                    @Override
                    public void run() {
                        invokeListener(listener, event);
                    }
                });
            } else {
                invokeListener(listener, event);
            }
        }
    }

    private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
        return ResolvableType.forInstance(event);
    }

    /**
     * Invoke the given listener with the given event.
     * @param listener the ApplicationListener to invoke
     * @param event the current event to propagate
     * @since 4.1
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                listener.onApplicationEvent(event);
            } catch (Throwable err) {
                errorHandler.handleError(err);
            }
        } else {
            listener.onApplicationEvent(event);
        }
    }
}

19 View Source File : SimpleApplicationEventMulticaster.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Set the {@link ErrorHandler} to invoke in case an exception is thrown
 * from a listener.
 * <p>Default is none, with a listener exception stopping the current
 * multicast and getting propagated to the publisher of the current event.
 * If a {@linkplain #setTaskExecutor task executor} is specified, each
 * individual listener exception will get propagated to the executor but
 * won't necessarily stop execution of other listeners.
 * <p>Consider setting an {@link ErrorHandler} implementation that catches
 * and logs exceptions (a la
 * {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_SUPPRESS_ERROR_HANDLER})
 * or an implementation that logs exceptions while nevertheless propagating them
 * (e.g. {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_PROPAGATE_ERROR_HANDLER}).
 * @since 4.1
 */
public void setErrorHandler(ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

19 View Source File : EmbeddedZooKeeper.java
License : Apache License 2.0
Project Creator : hengyunabc

/**
 * from: https://github.com/spring-projects/spring-xd/blob/v1.3.1.RELEASE/spring-xd-dirt/src/main/java/org/springframework/xd/dirt/zookeeper/ZooKeeperUtils.java
 *
 * Helper clreplaced to start an embedded instance of standalone (non clustered) ZooKeeper.
 *
 * NOTE: at least an external standalone server (if not an ensemble) are recommended, even for
 * {@link org.springframework.xd.dirt.server.singlenode.SingleNodeApplication}
 *
 * @author Patrick Peralta
 * @author Mark Fisher
 * @author David Turanski
 */
public clreplaced EmbeddedZooKeeper implements SmartLifecycle {

    /**
     * Logger.
     */
    private static final Logger logger = LoggerFactory.getLogger(EmbeddedZooKeeper.clreplaced);

    /**
     * ZooKeeper client port. This will be determined dynamically upon startup.
     */
    private final int clientPort;

    /**
     * Whether to auto-start. Default is true.
     */
    private boolean autoStartup = true;

    /**
     * Lifecycle phase. Default is 0.
     */
    private int phase = 0;

    /**
     * Thread for running the ZooKeeper server.
     */
    private volatile Thread zkServerThread;

    /**
     * ZooKeeper server.
     */
    private volatile ZooKeeperServerMain zkServer;

    /**
     * {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread.
     */
    private ErrorHandler errorHandler;

    private boolean daemon = true;

    /**
     * Construct an EmbeddedZooKeeper with a random port.
     */
    public EmbeddedZooKeeper() {
        clientPort = SocketUtils.findAvailableTcpPort();
    }

    /**
     * Construct an EmbeddedZooKeeper with the provided port.
     *
     * @param clientPort  port for ZooKeeper server to bind to
     */
    public EmbeddedZooKeeper(int clientPort, boolean daemon) {
        this.clientPort = clientPort;
        this.daemon = daemon;
    }

    /**
     * Returns the port that clients should use to connect to this embedded server.
     *
     * @return dynamically determined client port
     */
    public int getClientPort() {
        return this.clientPort;
    }

    /**
     * Specify whether to start automatically. Default is true.
     *
     * @param autoStartup whether to start automatically
     */
    public void setAutoStartup(boolean autoStartup) {
        this.autoStartup = autoStartup;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAutoStartup() {
        return this.autoStartup;
    }

    /**
     * Specify the lifecycle phase for the embedded server.
     *
     * @param phase the lifecycle phase
     */
    public void setPhase(int phase) {
        this.phase = phase;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getPhase() {
        return this.phase;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isRunning() {
        return (zkServerThread != null);
    }

    /**
     * Start the ZooKeeper server in a background thread.
     * <p>
     * Register an error handler via {@link #setErrorHandler} in order to handle
     * any exceptions thrown during startup or execution.
     */
    @Override
    public synchronized void start() {
        if (zkServerThread == null) {
            zkServerThread = new Thread(new ServerRunnable(), "ZooKeeper Server Starter");
            zkServerThread.setDaemon(daemon);
            zkServerThread.start();
        }
    }

    /**
     * Shutdown the ZooKeeper server.
     */
    @Override
    public synchronized void stop() {
        if (zkServerThread != null) {
            // The shutdown method is protected...thus this hack to invoke it.
            // This will log an exception on shutdown; see
            // https://issues.apache.org/jira/browse/ZOOKEEPER-1873 for details.
            try {
                Method shutdown = ZooKeeperServerMain.clreplaced.getDeclaredMethod("shutdown");
                shutdown.setAccessible(true);
                shutdown.invoke(zkServer);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            // It is expected that the thread will exit after
            // the server is shutdown; this will block until
            // the shutdown is complete.
            try {
                zkServerThread.join(5000);
                zkServerThread = null;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                logger.warn("Interrupted while waiting for embedded ZooKeeper to exit");
                // abandoning zk thread
                zkServerThread = null;
            }
        }
    }

    /**
     * Stop the server if running and invoke the callback when complete.
     */
    @Override
    public void stop(Runnable callback) {
        stop();
        callback.run();
    }

    /**
     * Provide an {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread. If none
     * is provided, only error-level logging will occur.
     *
     * @param errorHandler the {@link ErrorHandler} to be invoked
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Runnable implementation that starts the ZooKeeper server.
     */
    private clreplaced ServerRunnable implements Runnable {

        @Override
        public void run() {
            try {
                Properties properties = new Properties();
                File file = new File(System.getProperty("java.io.tmpdir") + File.separator + UUID.randomUUID());
                file.deleteOnExit();
                properties.setProperty("dataDir", file.getAbsolutePath());
                properties.setProperty("clientPort", String.valueOf(clientPort));
                QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig();
                quorumPeerConfig.parseProperties(properties);
                zkServer = new ZooKeeperServerMain();
                ServerConfig configuration = new ServerConfig();
                configuration.readFrom(quorumPeerConfig);
                zkServer.runFromConfig(configuration);
            } catch (Exception e) {
                if (errorHandler != null) {
                    errorHandler.handleError(e);
                } else {
                    logger.error("Exception running embedded ZooKeeper", e);
                }
            }
        }
    }
}

19 View Source File : EmbeddedZooKeeper.java
License : Apache License 2.0
Project Creator : apache

/**
 * from: https://github.com/spring-projects/spring-xd/blob/v1.3.1.RELEASE/spring-xd-dirt/src/main/java/org/springframework/xd/dirt/zookeeper/ZooKeeperUtils.java
 * <p>
 * Helper clreplaced to start an embedded instance of standalone (non clustered) ZooKeeper.
 * <p>
 * NOTE: at least an external standalone server (if not an ensemble) are recommended, even for
 * {@link org.springframework.xd.dirt.server.singlenode.SingleNodeApplication}
 *
 * @author Patrick Peralta
 * @author Mark Fisher
 * @author David Turanski
 */
public clreplaced EmbeddedZooKeeper implements SmartLifecycle {

    /**
     * Logger.
     */
    private static final Logger logger = LoggerFactory.getLogger(EmbeddedZooKeeper.clreplaced);

    /**
     * ZooKeeper client port. This will be determined dynamically upon startup.
     */
    private final int clientPort;

    /**
     * Whether to auto-start. Default is true.
     */
    private boolean autoStartup = true;

    /**
     * Lifecycle phase. Default is 0.
     */
    private int phase = 0;

    /**
     * Thread for running the ZooKeeper server.
     */
    private volatile Thread zkServerThread;

    /**
     * ZooKeeper server.
     */
    private volatile ZooKeeperServerMain zkServer;

    /**
     * {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread.
     */
    private ErrorHandler errorHandler;

    private boolean daemon = true;

    /**
     * Construct an EmbeddedZooKeeper with a random port.
     */
    public EmbeddedZooKeeper() {
        clientPort = SocketUtils.findAvailableTcpPort();
    }

    /**
     * Construct an EmbeddedZooKeeper with the provided port.
     *
     * @param clientPort port for ZooKeeper server to bind to
     */
    public EmbeddedZooKeeper(int clientPort, boolean daemon) {
        this.clientPort = clientPort;
        this.daemon = daemon;
    }

    /**
     * Returns the port that clients should use to connect to this embedded server.
     *
     * @return dynamically determined client port
     */
    public int getClientPort() {
        return this.clientPort;
    }

    /**
     * Specify whether to start automatically. Default is true.
     *
     * @param autoStartup whether to start automatically
     */
    public void setAutoStartup(boolean autoStartup) {
        this.autoStartup = autoStartup;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAutoStartup() {
        return this.autoStartup;
    }

    /**
     * Specify the lifecycle phase for the embedded server.
     *
     * @param phase the lifecycle phase
     */
    public void setPhase(int phase) {
        this.phase = phase;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getPhase() {
        return this.phase;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isRunning() {
        return (zkServerThread != null);
    }

    /**
     * Start the ZooKeeper server in a background thread.
     * <p>
     * Register an error handler via {@link #setErrorHandler} in order to handle
     * any exceptions thrown during startup or execution.
     */
    @Override
    public synchronized void start() {
        if (zkServerThread == null) {
            zkServerThread = new Thread(new ServerRunnable(), "ZooKeeper Server Starter");
            zkServerThread.setDaemon(daemon);
            zkServerThread.start();
        }
    }

    /**
     * Shutdown the ZooKeeper server.
     */
    @Override
    public synchronized void stop() {
        if (zkServerThread != null) {
            // The shutdown method is protected...thus this hack to invoke it.
            // This will log an exception on shutdown; see
            // https://issues.apache.org/jira/browse/ZOOKEEPER-1873 for details.
            try {
                Method shutdown = ZooKeeperServerMain.clreplaced.getDeclaredMethod("shutdown");
                shutdown.setAccessible(true);
                shutdown.invoke(zkServer);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            // It is expected that the thread will exit after
            // the server is shutdown; this will block until
            // the shutdown is complete.
            try {
                zkServerThread.join(5000);
                zkServerThread = null;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                logger.warn("Interrupted while waiting for embedded ZooKeeper to exit");
                // abandoning zk thread
                zkServerThread = null;
            }
        }
    }

    /**
     * Stop the server if running and invoke the callback when complete.
     */
    @Override
    public void stop(Runnable callback) {
        stop();
        callback.run();
    }

    /**
     * Provide an {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread. If none
     * is provided, only error-level logging will occur.
     *
     * @param errorHandler the {@link ErrorHandler} to be invoked
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Runnable implementation that starts the ZooKeeper server.
     */
    private clreplaced ServerRunnable implements Runnable {

        @Override
        public void run() {
            try {
                Properties properties = new Properties();
                File file = new File(System.getProperty("java.io.tmpdir") + File.separator + UUID.randomUUID());
                file.deleteOnExit();
                properties.setProperty("dataDir", file.getAbsolutePath());
                properties.setProperty("clientPort", String.valueOf(clientPort));
                QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig();
                quorumPeerConfig.parseProperties(properties);
                zkServer = new ZooKeeperServerMain();
                ServerConfig configuration = new ServerConfig();
                configuration.readFrom(quorumPeerConfig);
                zkServer.runFromConfig(configuration);
            } catch (Exception e) {
                if (errorHandler != null) {
                    errorHandler.handleError(e);
                } else {
                    logger.error("Exception running embedded ZooKeeper", e);
                }
            }
        }
    }
}

19 View Source File : EmbeddedZooKeeper.java
License : Apache License 2.0
Project Creator : apache

/**
 * from: https://github.com/spring-projects/spring-xd/blob/v1.3.1.RELEASE/spring-xd-dirt/src/main/java/org/springframework/xd/dirt/zookeeper/ZooKeeperUtils.java
 * <p>
 * Helper clreplaced to start an embedded instance of standalone (non clustered) ZooKeeper.
 * <p>
 * NOTE: at least an external standalone server (if not an ensemble) are recommended, even for
 * {@link org.springframework.xd.dirt.server.singlenode.SingleNodeApplication}
 *
 * @author Patrick Peralta
 * @author Mark Fisher
 * @author David Turanski
 */
public clreplaced EmbeddedZooKeeper implements SmartLifecycle {

    /**
     * Logger.
     */
    private static final Logger logger = LoggerFactory.getLogger(EmbeddedZooKeeper.clreplaced);

    /**
     * ZooKeeper client port. This will be determined dynamically upon startup.
     */
    private final int clientPort;

    /**
     * Whether to auto-start. Default is true.
     */
    private boolean autoStartup = true;

    /**
     * Lifecycle phase. Default is 0.
     */
    private int phase = 0;

    /**
     * Thread for running the ZooKeeper server.
     */
    private volatile Thread zkServerThread;

    /**
     * ZooKeeper server.
     */
    private volatile ZooKeeperServerMain zkServer;

    /**
     * {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread.
     */
    private ErrorHandler errorHandler;

    private boolean daemon = true;

    /**
     * Construct an EmbeddedZooKeeper with a random port.
     */
    public EmbeddedZooKeeper() {
        clientPort = SocketUtils.findAvailableTcpPort();
    }

    /**
     * Construct an EmbeddedZooKeeper with the provided port.
     *
     * @param clientPort port for ZooKeeper server to bind to
     */
    public EmbeddedZooKeeper(int clientPort, boolean daemon) {
        this.clientPort = clientPort;
        this.daemon = daemon;
    }

    /**
     * Returns the port that clients should use to connect to this embedded server.
     *
     * @return dynamically determined client port
     */
    public int getClientPort() {
        return this.clientPort;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAutoStartup() {
        return this.autoStartup;
    }

    /**
     * Specify whether to start automatically. Default is true.
     *
     * @param autoStartup whether to start automatically
     */
    public void setAutoStartup(boolean autoStartup) {
        this.autoStartup = autoStartup;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getPhase() {
        return this.phase;
    }

    /**
     * Specify the lifecycle phase for the embedded server.
     *
     * @param phase the lifecycle phase
     */
    public void setPhase(int phase) {
        this.phase = phase;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isRunning() {
        return (zkServerThread != null);
    }

    /**
     * Start the ZooKeeper server in a background thread.
     * <p>
     * Register an error handler via {@link #setErrorHandler} in order to handle
     * any exceptions thrown during startup or execution.
     */
    @Override
    public synchronized void start() {
        if (zkServerThread == null) {
            zkServerThread = new Thread(new ServerRunnable(), "ZooKeeper Server Starter");
            zkServerThread.setDaemon(daemon);
            zkServerThread.start();
        }
    }

    /**
     * Shutdown the ZooKeeper server.
     */
    @Override
    public synchronized void stop() {
        if (zkServerThread != null) {
            // The shutdown method is protected...thus this hack to invoke it.
            // This will log an exception on shutdown; see
            // https://issues.apache.org/jira/browse/ZOOKEEPER-1873 for details.
            try {
                Method shutdown = ZooKeeperServerMain.clreplaced.getDeclaredMethod("shutdown");
                shutdown.setAccessible(true);
                shutdown.invoke(zkServer);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            // It is expected that the thread will exit after
            // the server is shutdown; this will block until
            // the shutdown is complete.
            try {
                zkServerThread.join(5000);
                zkServerThread = null;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                logger.warn("Interrupted while waiting for embedded ZooKeeper to exit");
                // abandoning zk thread
                zkServerThread = null;
            }
        }
    }

    /**
     * Stop the server if running and invoke the callback when complete.
     */
    @Override
    public void stop(Runnable callback) {
        stop();
        callback.run();
    }

    /**
     * Provide an {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread. If none
     * is provided, only error-level logging will occur.
     *
     * @param errorHandler the {@link ErrorHandler} to be invoked
     */
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    /**
     * Runnable implementation that starts the ZooKeeper server.
     */
    private clreplaced ServerRunnable implements Runnable {

        @Override
        public void run() {
            try {
                Properties properties = new Properties();
                File file = new File(System.getProperty("java.io.tmpdir") + File.separator + UUID.randomUUID());
                file.deleteOnExit();
                properties.setProperty("dataDir", file.getAbsolutePath());
                properties.setProperty("clientPort", String.valueOf(clientPort));
                QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig();
                quorumPeerConfig.parseProperties(properties);
                zkServer = new ZooKeeperServerMain();
                ServerConfig configuration = new ServerConfig();
                configuration.readFrom(quorumPeerConfig);
                zkServer.runFromConfig(configuration);
            } catch (Exception e) {
                if (errorHandler != null) {
                    errorHandler.handleError(e);
                } else {
                    logger.error("Exception running embedded ZooKeeper", e);
                }
            }
        }
    }
}

19 View Source File : SpringRabbitMQComponentConfiguration.java
License : Apache License 2.0
Project Creator : apache

/**
 * Send and receive messages from RabbitMQ using Spring RabbitMQ client.
 *
 * Generated by camel-package-maven-plugin - do not edit this file!
 */
@Generated("org.apache.camel.springboot.maven.SpringBootAutoConfigurationMojo")
@ConfigurationProperties(prefix = "camel.component.spring-rabbitmq")
public clreplaced SpringRabbitMQComponentConfiguration extends ComponentConfigurationPropertiesCommon {

    /**
     * Whether to enable auto configuration of the spring-rabbitmq component.
     * This is enabled by default.
     */
    private Boolean enabled;

    /**
     * Optional AMQP Admin service to use for auto declaring elements (queues,
     * exchanges, bindings). The option is a
     * org.springframework.amqp.core.AmqpAdmin type.
     */
    private AmqpAdmin amqpAdmin;

    /**
     * The connection factory to be use. A connection factory must be configured
     * either on the component or endpoint. The option is a
     * org.springframework.amqp.rabbit.connection.ConnectionFactory type.
     */
    private ConnectionFactory connectionFactory;

    /**
     * Specifies whether to test the connection on startup. This ensures that
     * when Camel starts that all the JMS consumers have a valid connection to
     * the JMS broker. If a connection cannot be granted then Camel throws an
     * exception on startup. This ensures that Camel is not started with failed
     * connections. The JMS producers is tested as well.
     */
    private Boolean testConnectionOnStartup = false;

    /**
     * Specifies whether the consumer should auto declare binding between
     * exchange, queue and routing key when starting. Enabling this can be good
     * for development to make it easy to standup exchanges, queues and bindings
     * on the broker.
     */
    private Boolean autoDeclare = false;

    /**
     * Specifies whether the consumer container should auto-startup.
     */
    private Boolean autoStartup = true;

    /**
     * Allows for bridging the consumer to the Camel routing Error Handler,
     * which mean any exceptions occurred while the consumer is trying to pickup
     * incoming messages, or the likes, will now be processed as a message and
     * handled by the routing Error Handler. By default the consumer will use
     * the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that
     * will be logged at WARN or ERROR level and ignored.
     */
    private Boolean bridgeErrorHandler = false;

    /**
     * The name of the dead letter exchange
     */
    private String deadLetterExchange;

    /**
     * The type of the dead letter exchange
     */
    private String deadLetterExchangeType = "direct";

    /**
     * The name of the dead letter queue
     */
    private String deadLetterQueue;

    /**
     * The routing key for the dead letter exchange
     */
    private String deadLetterRoutingKey;

    /**
     * How many times a Rabbitmq consumer will retry the same message if Camel
     * failed to process the message
     */
    private Integer maximumRetryAttempts = 5;

    /**
     * Whether a Rabbitmq consumer should reject the message without requeuing.
     * This enables failed messages to be sent to a Dead Letter Exchange/Queue,
     * if the broker is so configured.
     */
    private Boolean rejectAndDontRequeue = true;

    /**
     * Delay in msec a Rabbitmq consumer will wait before redelivering a message
     * that Camel failed to process
     */
    private Integer retryDelay = 1000;

    /**
     * The number of consumers
     */
    private Integer concurrentConsumers = 1;

    /**
     * To use a custom ErrorHandler for handling exceptions from the message
     * listener (consumer). The option is a
     * org.springframework.util.ErrorHandler type.
     */
    private ErrorHandler errorHandler;

    /**
     * To use a custom factory for creating and configuring ListenerContainer to
     * be used by the consumer for receiving messages. The option is a
     * org.apache.camel.component.springrabbit.ListenerContainerFactory type.
     */
    private ListenerContainerFactory listenerContainerFactory;

    /**
     * The maximum number of consumers (available only with SMLC)
     */
    private Integer maxConcurrentConsumers;

    /**
     * The type of the MessageListenerContainer
     */
    private String messageListenerContainerType = "DMLC";

    /**
     * Tell the broker how many messages to send to each consumer in a single
     * request. Often this can be set quite high to improve throughput.
     */
    private Integer prefetchCount = 250;

    /**
     * Custom retry configuration to use. If this is configured then the other
     * settings such as maximumRetryAttempts for retry are not in use. The
     * option is a
     * org.springframework.retry.interceptor.RetryOperationsInterceptor type.
     */
    private RetryOperationsInterceptor retry;

    /**
     * The time to wait for workers in milliseconds after the container is
     * stopped. If any workers are active when the shutdown signal comes they
     * will be allowed to finish processing as long as they can finish within
     * this timeout. The option is a long type.
     */
    private Long shutdownTimeout = 5000L;

    /**
     * Whether the producer should be started lazy (on the first message). By
     * starting lazy you can use this to allow CamelContext and routes to
     * startup in situations where a producer may otherwise fail during starting
     * and cause the route to fail being started. By deferring this startup to
     * be lazy then the startup failure can be handled during routing messages
     * via Camel's routing error handlers. Beware that when the first message is
     * processed then creating and starting the producer may take a little time
     * and prolong the total processing time of the processing.
     */
    private Boolean lazyStartProducer = false;

    /**
     * Specify the timeout in milliseconds to be used when waiting for a reply
     * message when doing request/reply messaging. The default value is 5
     * seconds. A negative value indicates an indefinite timeout. The option is
     * a long type.
     */
    private Long replyTimeout = 5000L;

    /**
     * Whether autowiring is enabled. This is used for automatic autowiring
     * options (the option must be marked as autowired) by looking up in the
     * registry to find if there is a single instance of matching type, which
     * then gets configured on the component. This can be used for automatic
     * configuring JDBC data sources, JMS connection factories, AWS Clients,
     * etc.
     */
    private Boolean autowiredEnabled = true;

    /**
     * Switch on ignore exceptions such as mismatched properties when declaring
     */
    private Boolean ignoreDeclarationExceptions = false;

    /**
     * To use a custom MessageConverter so you can be in control how to map
     * to/from a org.springframework.amqp.core.Message. The option is a
     * org.springframework.amqp.support.converter.MessageConverter type.
     */
    private MessageConverter messageConverter;

    /**
     * To use a custom MessagePropertiesConverter so you can be in control how
     * to map to/from a org.springframework.amqp.core.MessageProperties. The
     * option is a
     * org.apache.camel.component.springrabbit.MessagePropertiesConverter type.
     */
    private MessagePropertiesConverter messagePropertiesConverter;

    /**
     * To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter
     * header to and from Camel message. The option is a
     * org.apache.camel.spi.HeaderFilterStrategy type.
     */
    private HeaderFilterStrategy headerFilterStrategy;

    public AmqpAdmin getAmqpAdmin() {
        return amqpAdmin;
    }

    public void setAmqpAdmin(AmqpAdmin amqpAdmin) {
        this.amqpAdmin = amqpAdmin;
    }

    public ConnectionFactory getConnectionFactory() {
        return connectionFactory;
    }

    public void setConnectionFactory(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    public Boolean getTestConnectionOnStartup() {
        return testConnectionOnStartup;
    }

    public void setTestConnectionOnStartup(Boolean testConnectionOnStartup) {
        this.testConnectionOnStartup = testConnectionOnStartup;
    }

    public Boolean getAutoDeclare() {
        return autoDeclare;
    }

    public void setAutoDeclare(Boolean autoDeclare) {
        this.autoDeclare = autoDeclare;
    }

    public Boolean getAutoStartup() {
        return autoStartup;
    }

    public void setAutoStartup(Boolean autoStartup) {
        this.autoStartup = autoStartup;
    }

    public Boolean getBridgeErrorHandler() {
        return bridgeErrorHandler;
    }

    public void setBridgeErrorHandler(Boolean bridgeErrorHandler) {
        this.bridgeErrorHandler = bridgeErrorHandler;
    }

    public String getDeadLetterExchange() {
        return deadLetterExchange;
    }

    public void setDeadLetterExchange(String deadLetterExchange) {
        this.deadLetterExchange = deadLetterExchange;
    }

    public String getDeadLetterExchangeType() {
        return deadLetterExchangeType;
    }

    public void setDeadLetterExchangeType(String deadLetterExchangeType) {
        this.deadLetterExchangeType = deadLetterExchangeType;
    }

    public String getDeadLetterQueue() {
        return deadLetterQueue;
    }

    public void setDeadLetterQueue(String deadLetterQueue) {
        this.deadLetterQueue = deadLetterQueue;
    }

    public String getDeadLetterRoutingKey() {
        return deadLetterRoutingKey;
    }

    public void setDeadLetterRoutingKey(String deadLetterRoutingKey) {
        this.deadLetterRoutingKey = deadLetterRoutingKey;
    }

    public Integer getMaximumRetryAttempts() {
        return maximumRetryAttempts;
    }

    public void setMaximumRetryAttempts(Integer maximumRetryAttempts) {
        this.maximumRetryAttempts = maximumRetryAttempts;
    }

    public Boolean getRejectAndDontRequeue() {
        return rejectAndDontRequeue;
    }

    public void setRejectAndDontRequeue(Boolean rejectAndDontRequeue) {
        this.rejectAndDontRequeue = rejectAndDontRequeue;
    }

    public Integer getRetryDelay() {
        return retryDelay;
    }

    public void setRetryDelay(Integer retryDelay) {
        this.retryDelay = retryDelay;
    }

    public Integer getConcurrentConsumers() {
        return concurrentConsumers;
    }

    public void setConcurrentConsumers(Integer concurrentConsumers) {
        this.concurrentConsumers = concurrentConsumers;
    }

    public ErrorHandler getErrorHandler() {
        return errorHandler;
    }

    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    public ListenerContainerFactory getListenerContainerFactory() {
        return listenerContainerFactory;
    }

    public void setListenerContainerFactory(ListenerContainerFactory listenerContainerFactory) {
        this.listenerContainerFactory = listenerContainerFactory;
    }

    public Integer getMaxConcurrentConsumers() {
        return maxConcurrentConsumers;
    }

    public void setMaxConcurrentConsumers(Integer maxConcurrentConsumers) {
        this.maxConcurrentConsumers = maxConcurrentConsumers;
    }

    public String getMessageListenerContainerType() {
        return messageListenerContainerType;
    }

    public void setMessageListenerContainerType(String messageListenerContainerType) {
        this.messageListenerContainerType = messageListenerContainerType;
    }

    public Integer getPrefetchCount() {
        return prefetchCount;
    }

    public void setPrefetchCount(Integer prefetchCount) {
        this.prefetchCount = prefetchCount;
    }

    public RetryOperationsInterceptor getRetry() {
        return retry;
    }

    public void setRetry(RetryOperationsInterceptor retry) {
        this.retry = retry;
    }

    public Long getShutdownTimeout() {
        return shutdownTimeout;
    }

    public void setShutdownTimeout(Long shutdownTimeout) {
        this.shutdownTimeout = shutdownTimeout;
    }

    public Boolean getLazyStartProducer() {
        return lazyStartProducer;
    }

    public void setLazyStartProducer(Boolean lazyStartProducer) {
        this.lazyStartProducer = lazyStartProducer;
    }

    public Long getReplyTimeout() {
        return replyTimeout;
    }

    public void setReplyTimeout(Long replyTimeout) {
        this.replyTimeout = replyTimeout;
    }

    public Boolean getAutowiredEnabled() {
        return autowiredEnabled;
    }

    public void setAutowiredEnabled(Boolean autowiredEnabled) {
        this.autowiredEnabled = autowiredEnabled;
    }

    public Boolean getIgnoreDeclarationExceptions() {
        return ignoreDeclarationExceptions;
    }

    public void setIgnoreDeclarationExceptions(Boolean ignoreDeclarationExceptions) {
        this.ignoreDeclarationExceptions = ignoreDeclarationExceptions;
    }

    public MessageConverter getMessageConverter() {
        return messageConverter;
    }

    public void setMessageConverter(MessageConverter messageConverter) {
        this.messageConverter = messageConverter;
    }

    public MessagePropertiesConverter getMessagePropertiesConverter() {
        return messagePropertiesConverter;
    }

    public void setMessagePropertiesConverter(MessagePropertiesConverter messagePropertiesConverter) {
        this.messagePropertiesConverter = messagePropertiesConverter;
    }

    public HeaderFilterStrategy getHeaderFilterStrategy() {
        return headerFilterStrategy;
    }

    public void setHeaderFilterStrategy(HeaderFilterStrategy headerFilterStrategy) {
        this.headerFilterStrategy = headerFilterStrategy;
    }
}

19 View Source File : SpringRabbitMQComponentConfiguration.java
License : Apache License 2.0
Project Creator : apache

public void setErrorHandler(ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

18 View Source File : ThreadPoolTaskScheduler.java
License : MIT License
Project Creator : Vip-Augus

@Override
public <T> Future<T> submit(Callable<T> task) {
    ExecutorService executor = getScheduledExecutor();
    try {
        Callable<T> taskToUse = task;
        ErrorHandler errorHandler = this.errorHandler;
        if (errorHandler != null) {
            taskToUse = new DelegatingErrorHandlingCallable<>(task, errorHandler);
        }
        return executor.submit(taskToUse);
    } catch (RejectedExecutionException ex) {
        throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
    }
}

18 View Source File : ThreadPoolTaskScheduler.java
License : MIT License
Project Creator : Vip-Augus

// TaskScheduler implementation
@Override
@Nullable
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
    ScheduledExecutorService executor = getScheduledExecutor();
    try {
        ErrorHandler errorHandler = this.errorHandler;
        if (errorHandler == null) {
            errorHandler = TaskUtils.getDefaultErrorHandler(true);
        }
        return new ReschedulingRunnable(task, trigger, executor, errorHandler).schedule();
    } catch (RejectedExecutionException ex) {
        throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
    }
}

18 View Source File : SimpleApplicationEventMulticaster.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Invoke the given listener with the given event.
 * @param listener the ApplicationListener to invoke
 * @param event the current event to propagate
 * @since 4.1
 */
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
    ErrorHandler errorHandler = getErrorHandler();
    if (errorHandler != null) {
        try {
            doInvokeListener(listener, event);
        } catch (Throwable err) {
            errorHandler.handleError(err);
        }
    } else {
        doInvokeListener(listener, event);
    }
}

18 View Source File : TracedThreadPoolTaskSchedulerTest.java
License : Apache License 2.0
Project Creator : opentracing-contrib

@Test
public void setErrorHandler() {
    final ErrorHandler errorHandler = mock(ErrorHandler.clreplaced);
    scheduler.setErrorHandler(errorHandler);
    verify(delegate).setErrorHandler(errorHandler);
}

18 View Source File : TracedThreadPoolTaskScheduler.java
License : Apache License 2.0
Project Creator : opentracing-contrib

@Override
public void setErrorHandler(ErrorHandler errorHandler) {
    delegate.setErrorHandler(errorHandler);
}

See More Examples