1 InitialContext initialContext = new InitialContext();
2 EJBHome ejbHome = (EJBHome) initialContext.lookup(jndiLocation);
3 Class ejbHomeClass = ejbHome.getClass();
4 Method createMethod = ejbHomeClass.getMethod("create", new Class[] { });
The exception is thrown from line 2 when the code executes the initial context lookup and stores it in an EJBHome object.
I have seen this issue several times and tried several solutions such as including the j2ee.jar in the classpath and manifest. However, their solutions might not apply to this issue since it occurs on a thread.
You should not use user-defined threads with EJB.
The EJB container is responsible for managing system-related functionality such as security, threading, resource pooling, and so on. In order to control these facets of component operation, the container places certain restrictions on the components it manages.
See http://www.oracle.com/technetwork/java/restrictions-142267.html
Related
For various reasons I need to perform a manual lookup of SessionContext. In JBoss5, the solution
InitialContext initialContext = new InitialContext();
SessionContext sessionContext = (SessionContext) initialContext.lookup("java:comp/EJBContext");
has served med well, but from JBoss 7 I instead get a
javax.naming.NameNotFoundException: EJBContext -- service jboss.naming.context.java.global.EJBContext
Has something changed in how context is looked up in JBoss 7.2, or is my deployment lacking anything vital? For reference, standard injection works fine, this is the only lookup that fails. Or am I doing something terribly wrong (besides performing a manual lookup of SessionContext)?
According to specification of Java EJB (this one is for EJB 3.2. but nothing changed about EJBContext from previous one, EJB 3.x), you can inject EJBContext into your components either using annotation #Resource or manually via lookup (section 11.15):
The container must make a component’s EJBContext interface available either through injection
using the Resource annotation or in JNDI under the name java:comp/EJBContext
Standard way of looking up for EJB resource is via EJBContext.lookup method but there is also JNDI way which is the only possibilities if you don't have already EJBContext:
Context initCtx = new InitialContext();
EJBContext ejbCtx = (EJBContext) initCtx.lookup("java:comp/EJBContext");
This is exactly what you did, so what is wrong? There are two things, which one I'm not sure about. First, with manually lookup it's sometime needed to assign resource to component with annotation at class level:
#Resource(name = "EJBContext", type = javax.ejb.EJBContext)
public class MyComponent {
...
}
but I'm not sure is it needed for EJBContext as well, I guess not. The second thing, more important and critical - according to specification once again:
EJBContext objects accessed through the naming environment are only valid within the bean
instance that performed the lookup.
this one is section 11.15.1, and the next one, section 11.15.2:
The Container Provider is responsible for providing an appropriate EJBContext object to the refer-
encing component. The object returned must be of the appropriate specific type for the bean requesting
injection or performing the lookup—that is, the Container Provider must return an instance of the SessionContext interface to referencing session beans and an instance of the MessageDrivenCon-
text interface to message-driven beans.
Those both mean that injection and lookup for EJBContext are only valid in Enterprise Java Beans, so those which are annotated with #MessageDriven, #Stateful, #Singleton or #Stateless (or described as EJBs in deployment descriptor file, also as EJB 2.x Specification). Maybe your component isn't valid EJB and it's why lookup isn't working? This is only suggestion of course.
There's one more possibilities to get EJBContext (more correctly SessionContext). Your component should implements SessionBean interface which has setSessionContext(SessionContext sessionContext) method. This method should be invoked by EJB container every time when component is used (injected somewhere, invoked by client or timeout, especially when it's created) and inside this method you should assign sessionContext parameter to bean's field.
EDIT:
I found classloader leak in my webapplication.
It boils down to 3rd party library initializing CORBA via JNDI's COS naming service and not exposing a call to cleanly shutdown JNDI's context. This leaves some CORBA related threads and other resources referencing my webapp classloader and preventing it from being garbage collected. This results in OutOfMemory Error: PermGen after few redeploys/reloads.
For now I increased the PermGen memory in JVM and it makes the intervals between server crashes longer. This obviously is not a fix but a workaround (and a poor one for that matter).
I guess my question is is there any way I can cleanly shutdown JNDI context without holding reference to it. My instincts tell me no, but maybe I don't know about some magic feature of JNDI that would allow me to get hold of that context.
So the way the 3rd party library initializes CORBA objects is something along this lines (exception handling and other details omited for brevity):
private CorbaObjectAggregate initCorba() {
InitialContext ctx = null;
CorbaObjectAggregate corbaObjects = new CorbaObjectAggregate();
ORB orb = null;
Properties env = getContextEnvironment();
String[] args = null;
orb = ORB.init(args, null);
env.put("java.naming.corba.orb", orb);
ctx = new InitialContext(env);
//a bunch of object lookups follow
corbaObjects.someCorbaObjectReference = (SomeCorbaObjectClass) ctx.lookup("somePaht");
return corbaObjects;
}
So the reference to ctx is gone after that method finishes executing...
I tried stopping the threads manually but it didn't fix the leak. I guess there are some other corba resources holding onto classloader. I suppose I could try to hunt them down in some cleanup method and free the classloader this way, but I was hoping for some cleaner solution.
Just for clarity, the 3rd party library is closed source and I can't really change it. It's also not viable option to get support form the company behind it.
That is going to be tricky to fix. There are likely to be two issues:
- classes loaded from the JAR holding a reference to the web-app class loader
- threads started by that process having the web-app class loader as their context class-loader.
Something along the following lines should help:
Move the JAR to $CATALINA_BASE/lib. That will mean that the classes are loaded by the common class loader. The down side is that they are also visible to and shared by every web application.
Find out where in your application the initialisation is triggered. Before that code executes, set the thread context class loader to the system class loader (or the parent of the current (web-app) class loader) and reset the thread context class loader after the init call. That should mean any threads created do not have the web-app class loader as the context class loader.
If threads get created at other points in time, fixing this could get very tricky, very quickly.
For some background that may help understand what is going on, see:
http://people.apache.org/~markt/presentations/2010-11-04-Memory-Leaks-60mins.pdf
To see the sort of thing Tomcat does internally to work-around these issues see:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java?view=annotate
I'm looking for a lib that allow me to do
define a worker that will be invoked once on a specific time in the future (not need the re-schedule / cron like featrure) i.e. a Timer
The worker should accept a context which withe some parameters / inputs
all should be persistent in the DB (or file) the worker
worker should be managed by spring -- spring should instantiate the worker so it can be injected with dependencies
be able to create timers dynamically via API and not just statically via spring XML beans
nice to have:
support a cluster i.e. have several nodes that can host a worker. each store jobn in the DB will cause invokaction of ONE work on one of the nods
I've examined several alternatives none meets the requirements:
Quartz
when using org.springframework.scheduling.quartz.JobDetailBean makes quartz create your worker instance (and not by spring) so you can't get dependecy ijection, (which will lead me to use Service Locator which I want to avoid)
while using org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean you can't get a context. your Worker expose one public method that accepts no arguments.In addition when using MethodInvokingJobDetailFactoryBean you can't use persistence (form the Javadoc)
Note: JobDetails created via this FactoryBean are not serializable and thus not suitable for persistent job stores. You need to implement your own Quartz Job as a thin wrapper for each case where you want a persistent job to delegate to a specific service method.
Spring's Timer and simple JDK Timers does not support the persistence / cluster feature
I know I can impl thing myself using a DB and Spring (or even JDK) Timers but I prefer to use an a 3r party lib for that.
Any suggestions?
If you want to create the job details to generate triggers/job-details at runtime and still be able to use Spring DI on your beans you can refer to this blog post, it shows how to use SpringBeanJobFactory in conjunction with ObjectFactoryCreatingFactoryBean to create Quartz triggering objects at runtime with Spring injected beans.
For those interested in an alternative to Quartz, have a look at db-scheduler (https://github.com/kagkarlsson/db-scheduler). A persistent task/execution-schedule is kept in a single database table. It is guaranteed to be executed only once by a scheduler in the cluster.
Yes, see code example below.
Currently limited to a single string identifier for no format restriction. The scheduler will likely be extended in the future with better support for job-details/parameters.
The execution-time and context is persistent in the database. Binding a task-name to a worker is done when the Scheduler starts. The worker may be instantiated by Spring as long as it implements the ExecutionHandler interface.
See 3).
Yes, see code example below.
Code example:
private static void springWorkerExample(DataSource dataSource, MySpringWorker mySpringWorker) {
// instantiate and start the scheduler somewhere in your application
final Scheduler scheduler = Scheduler
.create(dataSource)
.threads(2)
.build();
scheduler.start();
// define a task and a handler that named task, MySpringWorker implements the ExecutionHandler interface
final OneTimeTask oneTimeTask = ComposableTask.onetimeTask("my-onetime-task", mySpringWorker);
// schedule a future execution for the task with a custom id (currently the only form for context supported)
scheduler.scheduleForExecution(LocalDateTime.now().plusDays(1), oneTimeTask.instance("1001"));
}
public static class MySpringWorker implements ExecutionHandler {
public MySpringWorker() {
// could be instantiated by Spring
}
#Override
public void execute(TaskInstance taskInstance, ExecutionContext executionContext) {
// called when the execution-time is reached
System.out.println("Executed task with id="+taskInstance.getId());
}
}
Your requirements 3 and 4 do not really make sense to me: how can you have the whole package (worker + work) serialized and have it wake up magically and do its work? Shouldn't something in your running system do this at the proper time? Shouldn't this be the worker in the first place?
My approach would be this: create a Timer that Spring can instantiate and inject dependencies to. This Timer would then load its work / tasks from persistent storage, schedule them for execution and execute them. Your class can be a wrapper around java.util.Timer and not deal with the scheduling stuff at all. You must implement the clustering-related logic yourself, so that only one Timer / Worker gets to execute the work / task.
I am attempting to use JNDI with a custom DataSource called CEDataSource. From my understanding for this to work I would have to create a custom factory as well.
So I created a custom factory that would return the CEDataSource object but now when I attempt to use this in Java with
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
// Look up our data source
CEDataSource ds = (CEDataSource)envCtx.lookup("jdbc/cePu");
I get the exception ClassCastException
"CEDataSource cannot be mapped to CEDataSource". I added the CEDataSource and the CEDataSourceFactory to the TOMCAT/lib folder as well as referenced this same jar on my deployed application.
Any help would be greatly appreciated on why this possible error may occur. Thanks
"CEDataSource cannot be mapped to CEDataSource" seems to point to the fact that it's not the same "CEDataSource" in both places.
What could be different is the classloader and this usually happens if you have the same jars/.class(es) in multiple locations.
Do you have multiple copies of your jar?
Try to have a single copy, maybe in the shared tomcat lib so it's loaded by the same classloader no matter from where you access it from.
It is actually not too difficult to start Tomcat under an Eclipse debug session (just put all the Bootstrap.jar in a project and add the System properties in the JVM parameters). II've done that many times, if only to dissect the bowels of that feline. Once this is done you can break on the class cast exception of the JNDI connection factory and you will then be able to see if your factory is called or not.
From what I remember Tomcat uses the DBCP DataSource. Actually repackaged under com.apache.tomcat.dbcp.dbcp.DataSource (IIRC).
So I would not be surprised if this is what you end up with as a result of your look-up.
With hindsight, I now realize I also forgot to mention that if any underlying class (for instance a JDBC driver) needed to create the instance of your CEDataSource is missing you also get this ClassCastException. Fair enough, but you always focus on the class itself and not on the other jars...
CEDataSource ds = (CEDataSource)envCtx.lookup("jdbc/cePu");
The lookup you are doing on jdbc/cePu is not of class type CEDataSource , it belongs to some other class type, that is why you are getting class cast exception. if you could show me the configuration for jdbc/cePu that would be helpful.
In our system we have multi-threaded processing engine. During processing each thread calls methods to retrieve data from the database. We determined that performance is greatly improved if methods called from the same thread use the same DB session (sessions are coming from the pool of course).
Is there any standard way in Spring to ensure such thing or we have to come up with our own custom solution?
UPDATE: Forgot to mention that same methods can be called in different context where they should use a standard way of getting the session from the pool
I did not see Spring anywhere in your question. So I assume you want a simple utility to do this.
class SessionUtil {
private ThreadLocal currentSession;
public Session getCurrentSession() {
if(currentSession.get() == null) {
Session s = //create new session
currentSession.set(s);
}
return (Session)currentSession.get();
}
}
The Thread local will ensure that within the same thread it is always the same session. If you are using Spring then the classes/utilities mentioned above (in other responses) should be perfect.
Spring has a class called TransactionSynchronizationManager. It stores the current Session in a ThreadLocal. The TransactionSynchronizationManager is not recommended for use by the developer, but you can try using it.
Session session = ((SessionHolder)
TransactionSynchronizationManager.getResource(sessionFactory)).getSession();
(if you are using EntityManager, simply replace "Session" with "EntityManager").
You can have the sessionFactory injected in your bean - it is per-application.
Take a look at this discussion.
Other options, which I think are preferable to manual thread-handling are:
Thread pooling
Spring batch
Spring-JMS integration
Spring 3.0 has a concept of thread-scoped beans (hovewer, this scope is not registered by default, see docs): 3.5 Bean scopes, 3.5.5.2 Using a custom scope
EDIT:
I say about this:
Thread-scoped beans As of Spring 3.0,
a thread scope is available, but is
not registered by default. For more
information, see the documentation for
SimpleThreadScope. For
instructions on how to register this
or any other custom scope, see
Section 3.5.5.2, “Using a custom
scope”.
Spring coordinates database sessions, connections and threads through it's Transaction Framework (actually, using its TransactionSynchronizationManager - see description here - but you really don't want to mess with that directly, it's fearsome). If you need to coordinate your threads, then this is by far the simplest way of doing it.
How you choose to use the framework, however, is up top you.