Author: andygumbrecht
Date: Tue Jul 31 13:19:32 2012
New Revision: 1367533
URL: http://svn.apache.org/viewvc?rev=1367533&view=rev
Log:
Fix null pointer from ParentClassLoaderFinder in standalone.
Provide mock getters/setters for quartz properties on
DefaultTimerThreadPoolAdapter, and a config warning, and fix thread pool size.
Make DaemonThreadFactory thread safe ;-)
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/ParentClassLoaderFinder.java
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/timer/DefaultTimerThreadPoolAdapter.java
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EjbTimerServiceImpl.java
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/DaemonThreadFactory.java
openejb/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java?rev=1367533&r1=1367532&r2=1367533&view=diff
==============================================================================
---
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
(original)
+++
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
Tue Jul 31 13:19:32 2012
@@ -1404,7 +1404,7 @@ public class Assembler extends Assembler
ParentClassLoaderFinder parentFinder =
SystemInstance.get().getComponent(ParentClassLoaderFinder.class);
ClassLoader parent = OpenEJB.class.getClassLoader();
if (parentFinder != null) {
- parent = parentFinder.getParentClassLoader();
+ parent = parentFinder.getParentClassLoader(parent);
}
return ClassLoaderUtil.createClassLoader(appInfo.path,
jars.toArray(new URL[jars.size()]), parent);
}
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/ParentClassLoaderFinder.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/ParentClassLoaderFinder.java?rev=1367533&r1=1367532&r2=1367533&view=diff
==============================================================================
---
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/ParentClassLoaderFinder.java
(original)
+++
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/ParentClassLoaderFinder.java
Tue Jul 31 13:19:32 2012
@@ -20,15 +20,17 @@ import org.apache.openejb.OpenEJB;
import org.apache.openejb.loader.SystemInstance;
public interface ParentClassLoaderFinder {
- ClassLoader getParentClassLoader();
+
+ ClassLoader getParentClassLoader(final ClassLoader fallback);
public static class Helper {
public static ClassLoader get() {
final ParentClassLoaderFinder parentFinder =
SystemInstance.get().getComponent(ParentClassLoaderFinder.class);
+ final ClassLoader fallback = OpenEJB.class.getClassLoader();
if (parentFinder != null) {
- return parentFinder.getParentClassLoader();
+ return parentFinder.getParentClassLoader(fallback);
}
- return OpenEJB.class.getClassLoader();
+ return fallback;
}
}
}
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/timer/DefaultTimerThreadPoolAdapter.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/timer/DefaultTimerThreadPoolAdapter.java?rev=1367533&r1=1367532&r2=1367533&view=diff
==============================================================================
---
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/timer/DefaultTimerThreadPoolAdapter.java
(original)
+++
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/timer/DefaultTimerThreadPoolAdapter.java
Tue Jul 31 13:19:32 2012
@@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit;
/**
* @version $Rev$ $Date$
*/
+@SuppressWarnings("UnusedDeclaration")
public class DefaultTimerThreadPoolAdapter implements ThreadPool {
private static final Logger logger = Logger.getInstance(LogCategory.TIMER,
"org.apache.openejb.util.resources");
@@ -44,6 +45,16 @@ public class DefaultTimerThreadPoolAdapt
private String instanceName;
+ /**
+ * Mock support for property: org.quartz.threadPool.threadCount
+ */
+ private int threadCount = 3;
+
+ /**
+ * Mock support for property: org.quartz.threadPool.threadPriority
+ */
+ private int threadPriority = Thread.NORM_PRIORITY;
+
private final Object threadAvailableLock = new Object();
private final boolean threadPoolExecutorUsed;
@@ -53,12 +64,12 @@ public class DefaultTimerThreadPoolAdapt
if (this.executor == null) {
- int size =
Integer.parseInt(SystemInstance.get().getProperty("openejb.timer.pool.size",
"2"));
- if (size < 2) {
- size = 2;
+ int size =
Integer.parseInt(SystemInstance.get().getProperty("openejb.timer.pool.size",
"3"));
+ if (size < 3) {
+ size = 3;
}
- this.executor = new ThreadPoolExecutor(2
+ this.executor = new ThreadPoolExecutor(size
, size
, 60L
, TimeUnit.SECONDS
@@ -158,4 +169,19 @@ public class DefaultTimerThreadPoolAdapt
//TODO Seems we should never try to shutdown the thread pool, as it is
shared in global scope
}
+ public int getThreadCount() {
+ return this.threadCount;
+ }
+
+ public void setThreadCount(final int threadCount) {
+ this.threadCount = threadCount;
+ }
+
+ public int getThreadPriority() {
+ return this.threadPriority;
+ }
+
+ public void setThreadPriority(final int threadPriority) {
+ this.threadPriority = threadPriority;
+ }
}
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EjbTimerServiceImpl.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EjbTimerServiceImpl.java?rev=1367533&r1=1367532&r2=1367533&view=diff
==============================================================================
---
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EjbTimerServiceImpl.java
(original)
+++
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EjbTimerServiceImpl.java
Tue Jul 31 13:19:32 2012
@@ -28,47 +28,33 @@ import org.apache.openejb.spi.ContainerS
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.SetAccessible;
-import org.quartz.Calendar;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
-import org.quartz.JobExecutionContext;
-import org.quartz.JobKey;
-import org.quartz.ListenerManager;
import org.quartz.Scheduler;
-import org.quartz.SchedulerContext;
import org.quartz.SchedulerException;
-import org.quartz.SchedulerMetaData;
import org.quartz.Trigger;
-import org.quartz.TriggerKey;
-import org.quartz.UnableToInterruptJobException;
import org.quartz.impl.StdSchedulerFactory;
-import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.triggers.AbstractTrigger;
-import org.quartz.spi.JobFactory;
+import org.quartz.simpl.SimpleThreadPool;
import javax.ejb.EJBContext;
import javax.ejb.EJBException;
import javax.ejb.ScheduleExpression;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
-import java.io.Serializable;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
-import java.lang.reflect.Field;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
-import java.util.List;
-import java.util.Map;
import java.util.Properties;
-import java.util.Set;
public class EjbTimerServiceImpl implements EjbTimerService, Serializable {
@@ -105,7 +91,7 @@ public class EjbTimerServiceImpl impleme
this.retryAttempts = retryAttempts;
}
- private void writeObject(final ObjectOutputStream out) throws
IOException {
+ private void writeObject(final ObjectOutputStream out) throws IOException {
out.writeUTF(deployment.getDeploymentID().toString());
out.writeBoolean(transacted);
out.writeInt(retryAttempts);
@@ -124,15 +110,23 @@ public class EjbTimerServiceImpl impleme
public static synchronized Scheduler getDefaultScheduler(BeanContext
deployment) {
final Properties properties = new Properties();
- properties.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,
SystemInstance.get().hasProperty(QUARTZ_THREAD_POOL_ADAPTER) ?
SystemInstance.get().getOptions().get(QUARTZ_THREAD_POOL_ADAPTER, "")
- : DefaultTimerThreadPoolAdapter.class.getName());
+ final SystemInstance systemInstance = SystemInstance.get();
+ final String defaultThreadPool =
DefaultTimerThreadPoolAdapter.class.getName();
+ properties.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,
systemInstance.hasProperty(QUARTZ_THREAD_POOL_ADAPTER) ?
systemInstance.getOptions().get(QUARTZ_THREAD_POOL_ADAPTER,
SimpleThreadPool.class.getName())
+ : defaultThreadPool);
properties.put(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME,
"OpenEJB-TimerService-Scheduler");
updateProperties(properties, null);
boolean newInstance = updateProperties(properties,
deployment.getEjbName() + ".")
|| updateProperties(properties, deployment.getModuleName() +
"." + deployment.getEjbName() + ".");
- final Scheduler scheduler =
SystemInstance.get().getComponent(Scheduler.class);
+ if
(defaultThreadPool.equals(properties.get(StdSchedulerFactory.PROP_THREAD_POOL_CLASS))
+ && properties.containsKey("org.quartz.threadPool.threadCount")
+ & !properties.containsKey("openejb.timer.pool.size")) {
+ log.info("Found property 'org.quartz.threadPool.threadCount' for
default thread pool, please use 'openejb.timer.pool.size' instead");
+ }
+
+ final Scheduler scheduler =
systemInstance.getComponent(Scheduler.class);
Scheduler thisScheduler;
if (scheduler == null || newInstance) {
try {
@@ -151,7 +145,7 @@ public class EjbTimerServiceImpl impleme
}
if (!newInstance) {
- SystemInstance.get().setComponent(Scheduler.class,
thisScheduler);
+ systemInstance.setComponent(Scheduler.class, thisScheduler);
}
} else {
thisScheduler = scheduler;
@@ -160,8 +154,8 @@ public class EjbTimerServiceImpl impleme
}
private static boolean updateProperties(final Properties properties, final
String prefix) {
- boolean updated = false;
- for (String key:
SystemInstance.get().getProperties().stringPropertyNames()) {
+ boolean updated = false;
+ for (String key :
SystemInstance.get().getProperties().stringPropertyNames()) {
if (key.startsWith("org.quartz")) { // global config
final String value =
SystemInstance.get().getOptions().get(key, (String) null);
if (value != null) {
@@ -200,15 +194,18 @@ public class EjbTimerServiceImpl impleme
}
}
+
+ @Override
public void start() throws TimerStoreException {
- // load saved timers
- Collection<TimerData> timerDatas = timerStore.loadTimers(this,
(String)deployment.getDeploymentID());
+ // load saved timers
+ Collection<TimerData> timerDatas = timerStore.loadTimers(this,
(String) deployment.getDeploymentID());
// schedule the saved timers
for (TimerData timerData : timerDatas) {
initializeNewTimer(timerData);
}
}
+ @Override
public void stop() {
// stop all timers
for (TimerData timerData : timerStore.getTimers((String)
deployment.getDeploymentID())) {
@@ -228,13 +225,14 @@ public class EjbTimerServiceImpl impleme
/**
* Called from TimerData and start when a timer should be scheduled with
the java.util.Timer.
+ *
* @param timerData the timer to schedule
*/
public void schedule(TimerData timerData) {
if (scheduler == null) throw new IllegalStateException("scheduler is
configured properly");
-
+
timerData.setScheduler(scheduler);
-
+
Trigger trigger = timerData.getTrigger();
if (trigger instanceof AbstractTrigger) { // is the case
AbstractTrigger<?> atrigger = (AbstractTrigger<?>) trigger;
@@ -245,7 +243,7 @@ public class EjbTimerServiceImpl impleme
}
JobDataMap triggerDataMap = trigger.getJobDataMap();
triggerDataMap.put(EjbTimeoutJob.EJB_TIMERS_SERVICE, this);
- triggerDataMap.put(EjbTimeoutJob.TIMER_DATA,timerData);
+ triggerDataMap.put(EjbTimeoutJob.TIMER_DATA, timerData);
try {
scheduler.scheduleJob(trigger);
} catch (Exception e) {
@@ -256,6 +254,7 @@ public class EjbTimerServiceImpl impleme
/**
* Call back from TimerData and ejbTimeout when a timer has been cancelled
(or is complete) and should be removed from stores.
+ *
* @param timerData the timer that was cancelled
*/
public void cancelled(TimerData timerData) {
@@ -265,18 +264,20 @@ public class EjbTimerServiceImpl impleme
/**
* Returns a timerData to the TimerStore, if a cancel() is rolled back.
+ *
* @param timerData the timer to be returned to the timer store
*/
public void addTimerData(TimerData timerData) {
try {
timerStore.addTimerData(timerData);
} catch (Exception e) {
- log.warning("Could not add timer of type "+
timerData.getType().name() + " due to " + e.getMessage());
+ log.warning("Could not add timer of type " +
timerData.getType().name() + " due to " + e.getMessage());
}
}
+ @Override
public Timer getTimer(long timerId) {
- TimerData timerData =
timerStore.getTimer((String)deployment.getDeploymentID(), timerId);
+ TimerData timerData = timerStore.getTimer((String)
deployment.getDeploymentID(), timerId);
if (timerData != null) {
return timerData.getTimer();
} else {
@@ -284,11 +285,12 @@ public class EjbTimerServiceImpl impleme
}
}
+ @Override
public Collection<Timer> getTimers(Object primaryKey) throws
IllegalStateException {
checkState();
Collection<Timer> timers = new ArrayList<Timer>();
- for (TimerData timerData :
timerStore.getTimers((String)deployment.getDeploymentID())) {
+ for (TimerData timerData : timerStore.getTimers((String)
deployment.getDeploymentID())) {
timers.add(timerData.getTimer());
}
return timers;
@@ -359,7 +361,7 @@ public class EjbTimerServiceImpl impleme
@Override
public Timer createTimer(Object primaryKey, Method timeoutMethod,
ScheduleExpression scheduleExpression, TimerConfig timerConfig) {
- if(scheduleExpression == null) {
+ if (scheduleExpression == null) {
throw new IllegalArgumentException("scheduleExpression is null");
}
//TODO add more schedule expression validation logic ?
@@ -377,14 +379,15 @@ public class EjbTimerServiceImpl impleme
return timerStore;
}
- public Scheduler getScheduler(){
+ public Scheduler getScheduler() {
return scheduler;
}
- private void initializeNewTimer(TimerData timerData){
+ private void initializeNewTimer(TimerData timerData) {
// mark this as a new timer... when the transaction completes it will
schedule the timer
timerData.newTimer();
}
+
/**
* Insure that timer methods can be invoked for the current operation on
this Context.
*/
@@ -395,7 +398,7 @@ public class EjbTimerServiceImpl impleme
/**
* This method calls the ejbTimeout method and starts a transaction if the
timeout is transacted.
- *
+ * <p/>
* This method will retry failed ejbTimeout calls until retryAttempts is
exceeded.
*
* @param timerData the timer to call.
@@ -422,7 +425,7 @@ public class EjbTimerServiceImpl impleme
RpcContainer container = (RpcContainer)
deployment.getContainer();
Method ejbTimeout = timerData.getTimeoutMethod();
SetAccessible.on(ejbTimeout);
- container.invoke(deployment.getDeploymentID(),
InterfaceType.TIMEOUT, ejbTimeout.getDeclaringClass(), ejbTimeout, new Object[]
{ timer }, timerData.getPrimaryKey());
+ container.invoke(deployment.getDeploymentID(),
InterfaceType.TIMEOUT, ejbTimeout.getDeclaringClass(), ejbTimeout, new
Object[]{timer}, timerData.getPrimaryKey());
} catch (RuntimeException e) {
retry = true;
// exception from a timer does not necessairly mean failure
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/DaemonThreadFactory.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/DaemonThreadFactory.java?rev=1367533&r1=1367532&r2=1367533&view=diff
==============================================================================
---
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/DaemonThreadFactory.java
(original)
+++
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/DaemonThreadFactory.java
Tue Jul 31 13:19:32 2012
@@ -17,6 +17,7 @@
package org.apache.openejb.util;
import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
import static org.apache.openejb.util.Join.join;
@@ -26,7 +27,7 @@ import static org.apache.openejb.util.Jo
public class DaemonThreadFactory implements ThreadFactory {
private final String name;
- private transient int ids;
+ private AtomicInteger ids = new AtomicInteger(0);
public DaemonThreadFactory(Object... name) {
this.name = join(" ", name);
@@ -45,8 +46,9 @@ public class DaemonThreadFactory impleme
return strings;
}
+ @Override
public Thread newThread(Runnable runnable) {
- Thread t = new Thread(runnable, name + " thread " + (ids++));
+ Thread t = new Thread(runnable, (name + "-" + ids.incrementAndGet()));
t.setDaemon(true);
return t;
}
Modified:
openejb/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java?rev=1367533&r1=1367532&r2=1367533&view=diff
==============================================================================
---
openejb/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
(original)
+++
openejb/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
Tue Jul 31 13:19:32 2012
@@ -750,8 +750,7 @@ public class TomcatWebAppBuilder impleme
contextInfo =
addContextInfo(standardContext.getHostname(), standardContext);
contextInfo.standardContext = standardContext; // ensure
to do it before an exception can be thrown
- final AppInfo appInfo =
configurationFactory.configureApplication(appModule);
- contextInfo.appInfo = appInfo;
+ contextInfo.appInfo =
configurationFactory.configureApplication(appModule);
appContext = a.createApplication(contextInfo.appInfo,
classLoader);
// todo add watched resources to context
@@ -809,7 +808,7 @@ public class TomcatWebAppBuilder impleme
if (!contextInfo.appInfo.webAppAlone) {
updateInjections(injections, classLoader, false);
- for (BeanContext bean : appContext.getBeanContexts()) { //
TODO: how if the same class in multiple webapps?
+ for (final BeanContext bean :
appContext.getBeanContexts()) { // TODO: how if the same class in multiple
webapps?
updateInjections(bean.getInjections(), classLoader,
true);
}
}
@@ -860,7 +859,7 @@ public class TomcatWebAppBuilder impleme
}
}
- private static void updateInjections(Collection<Injection> injections,
ClassLoader classLoader, boolean keepInjection) {
+ private static void updateInjections(final Collection<Injection>
injections, final ClassLoader classLoader, final boolean keepInjection) {
final Iterator<Injection> it = injections.iterator();
final List<Injection> newOnes = new ArrayList<Injection>();
while (it.hasNext()) {
@@ -1089,7 +1088,7 @@ public class TomcatWebAppBuilder impleme
// add servlets to webappinfo
if (currentWebAppInfo != null) {
- for (String mapping : standardContext.findServletMappings()) {
+ for (final String mapping : standardContext.findServletMappings())
{
final ServletInfo info = new ServletInfo();
info.servletName = standardContext.findServletMapping(mapping);
info.mappings.add(mapping);
@@ -1115,7 +1114,7 @@ public class TomcatWebAppBuilder impleme
if (webBeansContext == null) return null;
- for (WebContext web : appContext.getWebContexts()) {
+ for (final WebContext web : appContext.getWebContexts()) {
final String stdName =
removeFirstSlashAndWar(contextInfo.standardContext.getName());
if (stdName == null) {
continue;
@@ -1133,7 +1132,7 @@ public class TomcatWebAppBuilder impleme
return new WebBeansListener(webBeansContext);
}
- private static String removeFirstSlashAndWar(String name) {
+ private static String removeFirstSlashAndWar(final String name) {
if (name == null || "/".equals(name) || name.isEmpty()) {
return "";
}
@@ -1154,10 +1153,7 @@ public class TomcatWebAppBuilder impleme
// useful to disable web applications deployment
// it can be placed in the context.xml file, server.xml, ...
// see
http://tomcat.apache.org/tomcat-5.5-doc/config/context.html#Context_Parameters
- if (standardContext.getServletContext().getAttribute(IGNORE_CONTEXT)
!= null) return true;
- if
(standardContext.getServletContext().getInitParameter(IGNORE_CONTEXT) != null)
return true;
-
- return false;
+ return
standardContext.getServletContext().getAttribute(IGNORE_CONTEXT) != null ||
standardContext.getServletContext().getInitParameter(IGNORE_CONTEXT) != null;
}
/**
@@ -1387,6 +1383,7 @@ public class TomcatWebAppBuilder impleme
try {
file = file.getCanonicalFile();
} catch (IOException e) {
+ logger.debug(e.getMessage(),e);
}
return file;
}
@@ -1420,7 +1417,6 @@ public class TomcatWebAppBuilder impleme
* tomcat context instance.
*
* @param standardContext tomcat context instance
- * @return a openejb web module
*/
private void loadWebModule(final AppModule appModule, final
StandardContext standardContext) {
final WebModule webModule = appModule.getWebModules().get(0);
@@ -1549,8 +1545,7 @@ public class TomcatWebAppBuilder impleme
*/
private ContextInfo getContextInfo(final StandardContext standardContext) {
final String id = getId(standardContext);
- final ContextInfo contextInfo = infos.get(id);
- return contextInfo;
+ return infos.get(id);
}
/**
@@ -1563,10 +1558,8 @@ public class TomcatWebAppBuilder impleme
if (host == null) {
host = defaultHost;
}
- final String contextRoot = webAppContextRoot;
- final String id = host + "/" + contextRoot;
- final ContextInfo contextInfo = infos.get(id);
- return contextInfo;
+ final String id = host + "/" + webAppContextRoot;
+ return infos.get(id);
}
/**
@@ -1657,11 +1650,13 @@ public class TomcatWebAppBuilder impleme
}
}
+ @Override
public Map<ClassLoader, Map<String, Set<String>>> getJsfClasses() {
return jsfClasses;
}
- public ClassLoader getParentClassLoader() {
- return parentClassLoader;
+ @Override
+ public ClassLoader getParentClassLoader(final ClassLoader fallback) {
+ return (null != this.parentClassLoader ? this.parentClassLoader :
fallback);
}
}