Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* http://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.apache.synapse.commons.beanstalk.enterprise;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.commons.jmx.MBeanRegistrar;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* An Enterprise Beanstalk is used to retrieve Enterprise JavaBean (EJB) client stubs. This class
* implements Service Locator J2EE pattern and supports stateless and stateful session beans.
* Enterprise beanstalks can be configured in synapse.properties file. Parameters of the JNDI
* service to be looked up for EJBs should be provided with this configuration.
* Beanstalks cache EJB client stubs to improve efficiency by omitting excessive JNDI
* context creation and look ups. Cache timeout for both stateless and stateful session beans could
* be configured independently.
*/
public class EnterpriseBeanstalk {
private static final Log log = LogFactory.getLog(EnterpriseBeanstalk.class);
/**
* Name of the beanstalk
*/
private String name;
/**
* Properties used while initializing this beanstalk.
*/
private Properties props;
/**
* Executor that periodically runs the Cleaner.
*/
private ScheduledExecutorService scheduler;
/**
* Scheduled future that represents the scheduled Cleaner.
*/
private ScheduledFuture> scheduledFuture;
/**
* Cache timeout for stateless session bean stubs.
*/
private int statelessBeanTimeoutMinutes = 30;
/**
* Cache timeout for stateful session bean stubs.
*/
private int statefulBeanTimeoutMinutes = 30;
/**
* Warn limit for stateless session beans. A warning is generated when more than this many of
* stateless bean stubs are cached by this beanstalk.
*/
private int statelessBeanWarnLimit = Short.MAX_VALUE;
/**
* Warn limit for stateful session beans. A warning is generated when more than this many of
* stateful bean stubs are cached by this beanstalk.
*/
private int statefulBeanWarnLimit = Short.MAX_VALUE;
/**
* JNDI context constructed with the properties provided while initializing this beanstalk.
*/
private InitialContext initialCtx;
/**
* Stateless session bean stub cache.
*/
private Map statelessBeans = new ConcurrentHashMap();
/**
* Stateful session bean stub cache.
*/
private Map statefulBeans = new ConcurrentHashMap();
/**
* Constructs a new enterprise beanstalk with the given name and properties.
* @param name Name of the enterprise beanstalk.
* @param props Configuration properties. This should include properties of the JNDI service
* to be looked up for EJBs.
* @param scheduler ScheduledExecutorService for cleaning up timed-out stubs.
*/
public EnterpriseBeanstalk(String name, Properties props, ScheduledExecutorService scheduler) {
this.name = name;
this.scheduler = scheduler;
this.props = props;
}
/**
* Initialize the current beanstalk by creating the JNDI context, registering the MBean etc.
*/
public void init() {
if (log.isDebugEnabled()) {
log.debug("Initializing Beanstalk: " + name);
}
// Initialize the JNDI context.
try {
initialCtx = new InitialContext(props);
} catch (NamingException e) {
log.error("Could not initialize JNDI context for the Enterprise Beanstalk " +
"named '" + name + "'.", e);
return;
}
// Read settings from the provided properties.
if (props != null) {
String value;
value = props.getProperty(EnterpriseBeanstalkConstants.STATELESS_BEANS_TIMEOUT);
if (value != null) {
statelessBeanTimeoutMinutes = Integer.parseInt(value);
}
value = props.getProperty(EnterpriseBeanstalkConstants.STATEFUL_BEANS_TIMEOUT);
if (value != null) {
statefulBeanTimeoutMinutes = Integer.parseInt(value);
}
value = props.getProperty(EnterpriseBeanstalkConstants.STATELESS_BEANS_WARN_LIMIT);
if (value != null) {
statelessBeanWarnLimit = Integer.parseInt(value);
}
value = props.getProperty(EnterpriseBeanstalkConstants.STATEFUL_BEANS_WARN_LIMIT);
if (value != null) {
statefulBeanWarnLimit = Integer.parseInt(value);
}
}
// Schedule the cleaner that removes expired beans periodically.
int minDelay = Math.min(statelessBeanTimeoutMinutes, statefulBeanTimeoutMinutes);
scheduledFuture = scheduler.scheduleWithFixedDelay(
new Runnable() {
public void run() {
removeExpiredBeans();
}
}, minDelay, minDelay, TimeUnit.MINUTES);
// Register the MBean for this beanstalk.
MBeanRegistrar.getInstance().registerMBean(new EnterpriseBeanstalkView(this),
EnterpriseBeanstalkConstants.ENTERPRISE_BEANSTALK_MBEAN_CATEGORY_NAME, name);
if (log.isDebugEnabled()) {
log.debug("Successfully initialized Beanstalk: " + name);
}
}
/**
* Destroys the beanstalk by performing clean up.
*/
public void destroy() {
scheduledFuture.cancel(false);
MBeanRegistrar.getInstance().unRegisterMBean(
EnterpriseBeanstalkConstants.ENTERPRISE_BEANSTALK_MBEAN_CATEGORY_NAME, name);
}
/**
* Returns the name of this beanstalk.
*
* @return Name of the beanstalk.
*/
public String getName() {
return name;
}
/**
* Returns a client stub for the EJB with given class name, session id and jndi name. If the
* stub is already available in cache, it is retrieved from there. Otherwise, a JNDI lookup
* is performed with the given JNDI name.
*
* @param className Fully qualified name of the remote interface of the session bean.
* @param sessionId Session id for stateful beans. null for stateless ones.
* @param jndiName JNDI name of the EJB. null could be used if the bean is already available in
* the cache.
* @return Retrieved EJB client stub. null if the EJB is not found.
*/
public Object getEnterpriseBean(String className, String sessionId, String jndiName) {
return sessionId == null ?
findEjb(statelessBeans, className, sessionId, jndiName, statelessBeanWarnLimit) :
findEjb(statefulBeans, className, sessionId, jndiName, statefulBeanWarnLimit);
}
/**
* Remove the specified client stub from cache. If the stub is not removed using this
* method it will be automatically removed from the beanstalk after it times out.
* @param className Fully qualified name of the remote interface of the session bean.
* @param sessionId Session id for stateful session beans, null for stateless ones.
* @return EJB client stub that was removed from the beanstalk.
*/
public Object removeEnterpriseBean(String className, String sessionId) {
return (sessionId == null) ?
statelessBeans.remove(getMapKey(className, sessionId)) :
statefulBeans.remove(getMapKey(className, sessionId));
}
/**
* Removes expired stateless and stateful bean stubs from cache. Timeouts are configurable.
*/
public void removeExpiredBeans() {
removeExpiredBeansFromMap(statelessBeans, statelessBeanTimeoutMinutes);
removeExpiredBeansFromMap(statefulBeans, statefulBeanTimeoutMinutes);
}
/**
* Retrieves an EJB client stub from the cache, looks up in the JNDI service if it is not
* available in the cache. If the bean is found from JNDI lookup, it is added to the cache.
*
* @param map Cache to search the stub in.
* @param className Fully qualified name of the remote interface of the session bean.
* @param sessionId Session id for stateful beans. null for stateless ones.
* @param jndiName JNDI name of the EJB. null could be used if the bean is already available in
* the cache.
* @param warnLimit If this many of stubs are already available in the cache, a warning is
* generated before adding a new stub to it.
* @return Retrieved EJB client stub. null if the EJB is not found.
*/
private Object findEjb(Map map, String className, String sessionId,
String jndiName, int warnLimit) {
CacheEntry entry = map.get(getMapKey(className, sessionId));
if (entry == null && jndiName != null) {
synchronized (this) {
entry = map.get(getMapKey(className, sessionId));
if (entry == null) {
Object ejb = lookupInJndi(jndiName);
if (ejb != null) {
map.put(getMapKey(className, sessionId), entry = new CacheEntry(ejb));
int size = map.size();
if (size > warnLimit) {
String type = sessionId == null ? "stateless" : "stateful";
log.warn("Warn limit reached for " + type + " beans. Currently there " +
"are " + size + " " + type + " EJB stubs cached in '" + name +
"' " + "beanstalk.");
}
}
}
}
}
if (entry == null) {
return null;
} else {
entry.markLastAccessTime();
return entry.getBean();
}
}
/**
* Looks up the given resource in the JNDI service.
* @param jndiName JNDI name of the resource (EJB).
* @return Resource retrieved from the JNDI lookup. null if no resource is found.
*/
private Object lookupInJndi(String jndiName) {
try {
return initialCtx.lookup(jndiName);
} catch (NamingException ex) {
log.error("Lookup failed for JNDI name: " + jndiName, ex);
return null;
}
}
/**
* Remove stubs from the given map that have not been used for a time period longer than the
* provided timeout.
* @param map Bean stub cache.
* @param timeoutInMinutes Expiry timeout.
*/
private void removeExpiredBeansFromMap(Map map, int timeoutInMinutes) {
Iterator> itr = map.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry mapEntry = itr.next();
if (System.currentTimeMillis() - mapEntry.getValue().getLastAccessTime() >
timeoutInMinutes * 60L * 1000L) {
if (log.isDebugEnabled()) {
log.debug("Removing the timed-out EJB stub with key '" + mapEntry.getKey() +
"', from '" + name + "' beanstalk cache.");
}
itr.remove();
}
}
}
/**
* Derives the map key for this session bean.
* @param className Fully qualified name of the remote interface of the EJB.
* @param sessionId Session Id for stateful beans, null for stateless ones.
* @return Map key derived from the given parameters.
*/
private String getMapKey(String className, String sessionId) {
return sessionId == null ? className : className + "-" + sessionId;
}
Map getStatelessBeans() {
return statelessBeans;
}
Map getStatefulBeans() {
return statefulBeans;
}
}