spring StandardJmsActivationSpecFactory 源码
spring StandardJmsActivationSpecFactory 代码
文件路径:/spring-jms/src/main/java/org/springframework/jms/listener/endpoint/StandardJmsActivationSpecFactory.java
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jms.listener.endpoint;
import java.util.Map;
import jakarta.jms.JMSException;
import jakarta.jms.Queue;
import jakarta.jms.Session;
import jakarta.jms.Topic;
import jakarta.resource.spi.ActivationSpec;
import jakarta.resource.spi.ResourceAdapter;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.jms.support.destination.DestinationResolutionException;
import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.lang.Nullable;
/**
* Standard implementation of the {@link JmsActivationSpecFactory} interface.
* Supports the standard JMS properties as defined by the JMS 1.5 specification
* (Appendix B); ignores Spring's "maxConcurrency" and "prefetchSize" settings.
*
* <p>The 'activationSpecClass' property is required, explicitly defining
* the fully-qualified class name of the provider's ActivationSpec class
* (e.g. "org.apache.activemq.ra.ActiveMQActivationSpec").
*
* <p>Check out {@link DefaultJmsActivationSpecFactory} for an extended variant
* of this class, supporting some further default conventions beyond the plain
* JMS 1.5 specification.
*
* @author Juergen Hoeller
* @since 2.5
* @see #setActivationSpecClass
* @see DefaultJmsActivationSpecFactory
*/
public class StandardJmsActivationSpecFactory implements JmsActivationSpecFactory {
@Nullable
private Class<?> activationSpecClass;
@Nullable
private Map<String, String> defaultProperties;
@Nullable
private DestinationResolver destinationResolver;
/**
* Specify the fully-qualified ActivationSpec class name for the target
* provider (e.g. "org.apache.activemq.ra.ActiveMQActivationSpec").
*/
public void setActivationSpecClass(Class<?> activationSpecClass) {
this.activationSpecClass = activationSpecClass;
}
/**
* Specify custom default properties, with String keys and String values.
* <p>Applied to each ActivationSpec object before it gets populated with
* listener-specific settings. Allows for configuring vendor-specific properties
* beyond the Spring-defined settings in {@link JmsActivationSpecConfig}.
*/
public void setDefaultProperties(Map<String, String> defaultProperties) {
this.defaultProperties = defaultProperties;
}
/**
* Set the DestinationResolver to use for resolving destination names
* into the JCA 1.5 ActivationSpec "destination" property.
* <p>If not specified, destination names will simply be passed in as Strings.
* If specified, destination names will be resolved into Destination objects first.
* <p>Note that a DestinationResolver for use with this factory must be
* able to work <i>without</i> an active JMS Session: e.g.
* {@link org.springframework.jms.support.destination.JndiDestinationResolver}
* or {@link org.springframework.jms.support.destination.BeanFactoryDestinationResolver}
* but not {@link org.springframework.jms.support.destination.DynamicDestinationResolver}.
*/
public void setDestinationResolver(@Nullable DestinationResolver destinationResolver) {
this.destinationResolver = destinationResolver;
}
/**
* Return the {@link DestinationResolver} to use for resolving destinations names.
*/
@Nullable
public DestinationResolver getDestinationResolver() {
return this.destinationResolver;
}
@Override
public ActivationSpec createActivationSpec(ResourceAdapter adapter, JmsActivationSpecConfig config) {
Class<?> activationSpecClassToUse = this.activationSpecClass;
if (activationSpecClassToUse == null) {
activationSpecClassToUse = determineActivationSpecClass(adapter);
if (activationSpecClassToUse == null) {
throw new IllegalStateException("Property 'activationSpecClass' is required");
}
}
ActivationSpec spec = (ActivationSpec) BeanUtils.instantiateClass(activationSpecClassToUse);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(spec);
if (this.defaultProperties != null) {
bw.setPropertyValues(this.defaultProperties);
}
populateActivationSpecProperties(bw, config);
return spec;
}
/**
* Determine the ActivationSpec class for the given ResourceAdapter,
* if possible. Called if no 'activationSpecClass' has been set explicitly
* @param adapter the ResourceAdapter to check
* @return the corresponding ActivationSpec class, or {@code null}
* if not determinable
* @see #setActivationSpecClass
*/
@Nullable
protected Class<?> determineActivationSpecClass(ResourceAdapter adapter) {
return null;
}
/**
* Populate the given ApplicationSpec object with the settings
* defined in the given configuration object.
* <p>This implementation applies all standard JMS settings, but ignores
* "maxConcurrency" and "prefetchSize" - not supported in standard JCA 1.5.
* @param bw the BeanWrapper wrapping the ActivationSpec object
* @param config the configured object holding common JMS settings
*/
protected void populateActivationSpecProperties(BeanWrapper bw, JmsActivationSpecConfig config) {
String destinationName = config.getDestinationName();
if (destinationName != null) {
boolean pubSubDomain = config.isPubSubDomain();
Object destination = destinationName;
if (this.destinationResolver != null) {
try {
destination = this.destinationResolver.resolveDestinationName(null, destinationName, pubSubDomain);
}
catch (JMSException ex) {
throw new DestinationResolutionException(
"Cannot resolve destination name [" + destinationName + "]", ex);
}
}
bw.setPropertyValue("destination", destination);
bw.setPropertyValue("destinationType", pubSubDomain ? Topic.class.getName() : Queue.class.getName());
}
if (bw.isWritableProperty("subscriptionDurability")) {
bw.setPropertyValue("subscriptionDurability", config.isSubscriptionDurable() ? "Durable" : "NonDurable");
}
else if (config.isSubscriptionDurable()) {
// Standard JCA 1.5 "subscriptionDurability" apparently not supported...
throw new IllegalArgumentException("Durable subscriptions not supported by underlying provider");
}
if (config.isSubscriptionShared()) {
throw new IllegalArgumentException("Shared subscriptions not supported for JCA-driven endpoints");
}
if (config.getSubscriptionName() != null) {
bw.setPropertyValue("subscriptionName", config.getSubscriptionName());
}
if (config.getClientId() != null) {
bw.setPropertyValue("clientId", config.getClientId());
}
if (config.getMessageSelector() != null) {
bw.setPropertyValue("messageSelector", config.getMessageSelector());
}
applyAcknowledgeMode(bw, config.getAcknowledgeMode());
}
/**
* Apply the specified acknowledge mode to the ActivationSpec object.
* <p>This implementation applies the standard JCA 1.5 acknowledge modes
* "Auto-acknowledge" and "Dups-ok-acknowledge". It throws an exception in
* case of {@code CLIENT_ACKNOWLEDGE} or {@code SESSION_TRANSACTED}
* having been requested.
* @param bw the BeanWrapper wrapping the ActivationSpec object
* @param ackMode the configured acknowledgment mode
* (according to the constants in {@link jakarta.jms.Session})
* @see jakarta.jms.Session#AUTO_ACKNOWLEDGE
* @see jakarta.jms.Session#DUPS_OK_ACKNOWLEDGE
* @see jakarta.jms.Session#CLIENT_ACKNOWLEDGE
* @see jakarta.jms.Session#SESSION_TRANSACTED
*/
protected void applyAcknowledgeMode(BeanWrapper bw, int ackMode) {
if (ackMode == Session.SESSION_TRANSACTED) {
throw new IllegalArgumentException("No support for SESSION_TRANSACTED: Only \"Auto-acknowledge\" " +
"and \"Dups-ok-acknowledge\" supported in standard JCA 1.5");
}
else if (ackMode == Session.CLIENT_ACKNOWLEDGE) {
throw new IllegalArgumentException("No support for CLIENT_ACKNOWLEDGE: Only \"Auto-acknowledge\" " +
"and \"Dups-ok-acknowledge\" supported in standard JCA 1.5");
}
else if (bw.isWritableProperty("acknowledgeMode")) {
bw.setPropertyValue("acknowledgeMode",
ackMode == Session.DUPS_OK_ACKNOWLEDGE ? "Dups-ok-acknowledge" : "Auto-acknowledge");
}
else if (ackMode == Session.DUPS_OK_ACKNOWLEDGE) {
// Standard JCA 1.5 "acknowledgeMode" apparently not supported (e.g. WebSphere MQ 6.0.2.1)
throw new IllegalArgumentException("Dups-ok-acknowledge not supported by underlying provider");
}
}
}
相关信息
相关文章
spring DefaultJmsActivationSpecFactory 源码
spring JmsActivationSpecConfig 源码
spring JmsActivationSpecFactory 源码
spring JmsMessageEndpointFactory 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦