On most of applications servers, J2EE Ejb specification forbids creating threads "by hand", since these resources should be managed by the server.
But is there any way to get threads from Tomcat, Glassfish, Jboss etc.; thus access their ThreadPool?
You can use the commonj WorkManager. It was a proposal by IBM and BEA to provide a standard means to accomplish this task (access to container managed threads).
Although it was not included in the actual specification, there are implementations available for most containers.
Use in Weblogic
Use in WebSphere
Implementation for Tomcat, JBOSS and maybe others
Spring integration
The legal way to get threads from container is using JCA (Java Connector Architecture). The component you implement using this technology is called "resource adapter" and is packaged as rar file.
The implementation is pretty verbose but not too complicated in simple cases. So, good luck.
I've seen at least one utility class for getting ahold of Tomcat's threadpool, but it's not wise to go this route. Those threads are created to service your EJB or Servlet's requests, not for you to support the EJB or Servlet. Each one you take up is just another thread that won't be available to service requests to the container.
You could probably just throw in a static ThreadPool and use a static initializer to get around the EJB spec on this one, but you'd obviously have to make sure the thread code works well otherwise it could really bork your EJB.
Related
Chapter 126 of the OSGI Enterprise Release 5 specification mentions compatibility:
"Support the traditional JNDI programming model used by Java SE and Java EE clients."
and use of OSGI-unaware code:
"Clients and JNDI Context providers that are unaware of OSGi use static methods to connect to the
JRE JNDI implementation. The InitialContext class provides access to a Context from a provider and
providers use the static NamingManager methods to do object conversion and find URL Contexts.
This traditional model is not aware of OSGi and can therefore only be used reliably if the consequences
of this lack of OSGi awareness are managed."
but it is not clear to me if this text only applies to "legacy" code executed inside an OSGI bundle, or also to code outside the OSGI container, f ex in a scenario where the OSGI container is embedded in an application.
In an embedding scenario, there may be application code both outside and inside the OSGI container that performs JNDI calls, and as they execute in the same JVM they will share JNDI implementation.
Question: Should an OSGI JNDI implementation running in an embedded OSGI container allow OSGI-unaware code outside the container to perform its JNDI calls like usual, or is some porting to "OSGI-awareness" required?
Trying this out myself with Apache Karaf 2.3.0 (which uses Apache Aries JNDI 1.0.0) this doesn't seem to work, as Apache Aries requires JNDI client calls to originate from an OSGI bundle.
Partial stacktrace:
javax.naming.NoInitialContextException: The calling code's BundleContext could not be determined.
at org.apache.aries.jndi.OSGiInitialContextFactoryBuilder.getInitialContext(OSGiInitialContextFactoryBuilder.java:46)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307)
at javax.naming.InitialContext.init(InitialContext.java:242)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
Question: Is this correct behaviour, or is there a section of the specification I can refer to that is violated by this limitation?
I ran into same issue when trying to deploy Apache Karaf on Weblogic.
We use karaf through a servlet bridge - a war is deployed in weblogic which bridges all http requests to karaf.
I am running with the the following applications on weblogic:
app1 (uses JNDI)
app2
karaf-bridge (bridges requests to Karaf)
As soon as karaf starts the Aries JNDI implementation running inside Karaf sets InitialContextFactoryBuilder inside javax.naming.NamingManager to its own implementation. NamingManager holds a static reference to the initial context factory builder, so whichever implementation, irrespective of whether its running in an OSGI environment, sets this static reference becomes the JNDI provider.
In my case when app1 (non-OSGI) tries to do a new InitialContext, Aries JNDI tries to resolve it using the BundleContext and fails.
I fixed this using some very ugly hacks that involved extracting the javax.naming package from jre and installing it as a bundle in karaf.
So the answer to your question: I think the issue is really in the jre and not with OSGI on how JNDI lookup is managed.
I'm not sure if I understand the problem correctly... JNDI is a Service Provider Interface, and it needs some underlying implementation to run with. All you need to do is to provision it the OSGI container.
I would recommend creating single bundle with all jars needed by JNDI and export all packages. Then use Dynamic-Import: * to use it. It worked in our case (Eclipse RCP application with JBoss 5 JNDI used for EJB calls).
However if you need JNDI inside and outside of the container and you don't want to struggle with Classloading, I would recommend adding all jars to the applications classpath. This way it should be accessible in whole your application.
Apache Aries seems to have thought about this and have provided an implementation of JRE initial context factory builder (org.apache.aries.jndi.JREInitialContextFactoryBuilder) which seems to work. However, for this to work, I had to change Aries code that registers the JVM wide initial context factory builder. There may be another (and possibly better) way of achieving this. But this seemed to work.
Also, note that the problem does not stop at InitialContextFactoryBuilder being set in NamingManager. The same issue arises for ObjectFactoryBuilder (which is again set JVM wide in NamingManager). Depending on the JNDI provider you are trying to connect to, you may need to change that part of Aries JNDI code as well. e.g. for Tibco EMS JNDI connection, I had to tweak the code for OSGiObjectFactoryBuilder from Aries to return a Tibco specific ObjectFactory. This can be easily generalized using Context.OBJECT_FACTORIES environment value.
I've raised a JIRA for the same - https://issues.apache.org/jira/browse/ARIES-1127
Can someone clarify which of these scenarios can be done when implementing EJBs and if not which would be the appropriate solution?
Read Write a File within a EJB method.
Send via Socket or HtttClient a POST/GET HTTP request and manipulate its response.
Start threads within a EJB (Asynchrounous requests).
According to the EJB 3.1 Spec
"An enterprise bean must not use the java.io package to attempt to access files and directories in the file system"
Also
"The enterprise bean must not attempt to directly read or write a file descriptor.
Allowing the enterprise bean to read and write file descriptors directly could compromise security."
It looks a hell like a homework to me, so I'll try to encourage you to at least show "some" effort and find the answers yourself as all your questions are "Programmatic restrictions" for EJBs. These restrictions can be found in EJB specification here, Chapter 21 - Runtime Environment.
Read Write a File within a EJB method?
Yes, why shouldn't that be possible unless some file system restrictions are in place?
Send via Socket or HtttClient a post/get request and manipulate its response.
That's normally done by either using a servlet or a webservice.
With EJBs you can also do remote calls, e.g. by looking up the remote interface using JNDI and invoking methods on it.
Start threads within a EJB (Asynchrounous requests).
Yes and AFAIK with Java EE 6 you'd just have to add the #Asynchronous annotation.
I'm currently developing a small EJB application running on IBM Websphere Application Server 7 (Java EE 5). The app mainly consists of one MDB listening for incoming MQ messages which are transformed and stored in a DB. Currently I'm using a lot of Singleton/Factories to share configurations, mappings, datasource lookups etc. But this actually leads to some very hard to test code. The solution might be using a (simple) DI framework like guice/spring to inject the different instances. The question is: Where to place the initialization/ setup code? Where is the main entry point of the application? How can I inject instances into the MDBs?
it might be worth looking at backing off from using Guice, and trying to work with the injection mechanisms already available with Java EE 5.
Regarding finding a suitable "startup point", unfortunately the EJB specification does not define a way where you can have a bean run at startup. However, the web profile of the EE spec does have one -- you can add a WAR to your application, and set a servlet listener component:
http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletContextListener.html
You can set this to start whenever the application is loaded and started by the container (WebSphere). Watch out for classloader issues though.
Using Spring, you can do it via EJB3 interceptors, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/ejb.html#ejb-implementation-ejb3
Useful info on caveats are in the javadoc, make sure you read it: http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/ejb/interceptor/SpringBeanAutowiringInterceptor.html
On the Tomcat FAQ it says: "Tomcat is not an EJB server. Tomcat is not a full J2EE server."
But if I:
use Spring to supply an application context
annotate my entities with JPA
annotations (and use Hibernate as a
JPA provider)
configure C3P0 as a connection pooling data
source
annotate my service methods
with #Transactional (and use Atomikos
as JTA provider)
Use JAXB for marshalling and unmarshalling
and possibly add my own JNDI capability
then don't I effectively have a Java EE application server? And then aren't my beans EJBs? Or is there some other defining characteristic?
What is it that a Java EE compliant app server gives you that you can't easily/readily get from Tomcat with some 3rd party subsystems?
EJBs are JavaEE components that conform to the javax.ejb API.
JavaEE is a collection of APIs, you don't need to use all of them.
Tomcat is a "partial" JavaEE server, in that it only implements some of the JavaEE APIs, such as Servlets and JNDI. It doesn't implement e.g. EJB and JMS, so it's not a full JavaEE implementation.
If you added some additional bits and pieces (e.g. OpenEJB, HornetQ), you'd add the missing parts, and you'd end up with a full JavaEE server. But out of the box, Tomcat isn't that, and doesn't try to be.
But if I add (...) then don't I effectively have a Java EE application server? And then aren't my beans EJBs? Or is there some other defining characteristic?
No, you don't have a Java EE application server, a full-fledged Java EE application server is more than Tomcat + Spring + a standalone Transaction Manager. And even if you add a JMS provider and an EJB container, you still won't have a Java EE server. The glue between all parts is IMO important and is part of the added value of a Java EE container.
Regarding EJBs, the EJB specification is much more than JPA and specifices also Session Beans and Message Driven Beans (actually, I don't really consider JPA Entities as EJBs even if JPA is part of the EJB 3.0 specification in Java EE 5 for historical reasons - which is not true anymore in Java EE 6, JPA 2.0 and EJB 3.1 are separate specifications).
I should also mention that a Spring bean annotated with #Transactional is not equivalent to a Session Bean. A Java EE container can do more things with Session Beans (see below). You may not need them though but still, they are not strictly equivalent.
Last thing, Java EE containers implement a standard, the Spring container does not, it is proprietary.
What is it that a Java EE compliant app server gives you that you can't easily/readily get from Tomcat with some 3rd party subsystems?
As I said, I think that the "glue" is a part of the added value and highly contributes to the robustness of the whole. Then, ewernli's answer underlined very well what is difficult to achieve. I'd just add:
Clustering and Fail-over (to achieve fault-tolerance)
Administration facilities
Yes, a good Java EE server will do pretty neat things to improve fault tolerance (clustering of connection pools, JNDI tree, JMS destinations, automatic retry with idempotent beans, smart EJB clients, transaction recovery, migration of services, etc). For "mission critical" applications - the vast majority are not - this is important. And in such cases, libraries on top of the Servlet API are IMO not a replacement.
1) You're confusing JPA entities with EJBs. While JPA belongs to the EJB3 specification, it was always meant to be a standalone technology.
2) EJBs are: stateless beans, stateful beans and message driven beans. While each of these functionalities can easily be achieved using spring, spring just does not use this terminology. In Spring, you don't have POJO + "magic" as in EJBs, in Spring it's POJO + your own configuration (which sometimes feels like magic, too). The main difference is that spring does more and the application server does less, which is why a spring app is happy with a tomcat while an ejb3 app needs a 'real' application server.
In my opinion, 90% of applications can be deployed using spring + tomcat, ejb3 is rarely needed.
Indeed, if you put enough effort you can almost turn Tomcat/Spring into a full-fledged heavyweight application server :) You could even embed a portable EJB3 container...
What is it that a Java EE compliant app
server gives you that you can't
easily/readily get from Tomcat with
some 3rd party subsystems?
There are still a few features that are hard to get with 3rd party modules:
stateful session beans (SFSB)
extended persistence context
application client container / java web start
clustering depending on the app. server
CORBA interoperability
JCA integration ~
remoting ~
container-managed transactions ~
decent management of distributed transactions (e.g. recover heuristic tx)
Entries with ~ are also supported by Spring, but not so trivially, at least to my best knowledge.
A few more details in this answer: EJB vs Spring
Outside of the strict definition of what is and isn't an EJB, you're adding a lot of stuff to Tomcat. Even if what you have is an EJB server, it's not really plain Tomcat anymore.
The FAQ is correct: Tomcat is not an EJB server. However, it can be that or many other things if you pile on enough extra libraries and code.
An EJB implementation would be a bean written and packaged to run on any compliant EJB server. If you do what you describe, it may work, but it won't be portable to another vendor's application server.
So EJB is a standard that adheres to a specific specification and is therefore portable.
In practice many EJB's are not fully compliant or application server neutral. However, in the main they are, so the small incompatibilities would be much easier to fix if you changed application server vendors than attempting to move the architecture you described to a GlassFish, JBoss or Weblogic server.
EDIT: In response to your comment you would not have an EJB appropriately annotated and/or configured via XML in such a way that code that accessed it in EJB compliant ways would be able to use it without changes.
There are two angles to your comment. One is what functionality would you lose deploying on a JBoss or any of the others instead of Tomcat? Likely nothing, if you brought along all of the frameworks you relied on. However, if you wanted to move your code to Weblogic, for example, to use some of its features, then your code would need some likely significant changes to keep up.
I am not saying that you cannot replicate all EJB functionality (certainly the subset you care about) via other means, just that it is not the spec, and therefore not implementation independent.
then don't I effectively have a Java EE
application server? And then aren't my
beans EJB's? Or is there some other
defining characteristic?
Quick answer EJBs actually have to follow a Java EE specification. Tomcat is a Java EE container not an app server.
What is it that a Java EE compliant app
server gives you that you can't
easily/readily get from Tomcat with
some 3rd party subsystems?
Quick answer to your second question. In your case most likely nothing.
EJBs tend to be really heavy objects and people ended up using them to solve problems when they were essentially overkill. Frameworks like Spring were created to solve those problems without using EJBs. I think the first book where Spring was introduced was even called "J2EE development without EJB."
It appears that our implementation of using Quartz - JDBCJobStore along with Spring, Hibernate and Websphere is throwing unmanaged threads.
I have done some reading and found a tech article from IBM stating that the usage of Quartz with Spring will cause that. They make the suggestion of using CommnonJ to address this issue.
I have done some further research and the only examples I have seen so far all deal with the plan old JobStore that is not in a database.
So, I was wondering if anyone has an example of the solution for this issue.
Thanks
We have a working solution for this (two actually).
1) Alter the quartz source code to use a WorkManager daemon thread for the main scheduler thread. It works, but requires changing quarts. We didn't use this though since we didn't want maintain a hacked version of quartz. (That reminds me, I was going to submit this to the project but completely forgot)
2) Create a WorkManagerThreadPool to be used as the quartz threadpool. Implement the interface for the quartz ThreadPool, so that each task that is triggered within quartz is wrapped in a commonj Work object that will then be scheduled in the WorkManager. The key is that the WorkManager in the WorkManagerThreadPool has to be initialized before the scheduler is started, from a Java EE thread (such as servlet initialization). The WorkManagerThreadPool must then create a daemon thread which will handle all the scheduled tasks by creating and scheduling the new Work objects. This way, the scheduler (on its own thread) is passing the tasks to a managed thread (the Work daemon).
Not simple, and unfortunately I do not have code readily available to include.
Adding another answer to the thread, since i found a solution for this, finally.
My environment: WAS 8.5.5, Quartz 1.8.5, no Spring.
The problem i had was the (above stated) unmanaged thread causing a NamingException from ctx.lookup(myJndiUrl), that was instead correctly working in other application servers (JBoss, Weblogic); actually, Webpshere was firing an "incident" with the following message:
javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the server runtime is not able to associate the operation's thread with any J2EE application component. This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request. Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application. Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names.
The following steps solved the problem:
1) upgraded to quartz 1.8.6 (no code changes), just maven pom
2) added the following dep to classpath (in my case, EAR's /lib folder), to make the new WorkManagerThreadExecutor available
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-commonj</artifactId>
<version>1.8.6</version>
</dependency>
Note: in QTZ-113 or the official Quartz Documentation 1.x 2.x there's no mention on how to activate this fix.
3) added the following to quartz.properties ("wm/default" was the JNDI of the already configured DefaultWorkManager in my WAS 8.5.5, see Resources -> AsynchronousBeans -> WorkManagers in WAS console):
org.quartz.threadExecutor.class=org.quartz.custom.WorkManagerThreadExecutor
org.quartz.threadExecutor.workManagerName=wm/default
Note: right class is org.quartz.custom.WorkManagerThreadExecutor for quartz-scheduler-1.8.6 (tested), or org.quartz.commonj.WorkManagerThreadExecutor from 2.1.1 on (not tested, but verified within actual quartz-commonj's jars on maven's repos)
4) moved the JNDI lookup in the empty constructor of the quartz job (thanks to m_klovre's "Thread outside of the J2EE container"); that is, the constructor was being invoked by reflection (newInstance() method) from the very same J2EE context of my application, and had access to java:global namespace, while the execute(JobExecutionContext) method was still running in a poorer context, which was missing all of my application's EJBs
Hope this helps.
Ps. as a reference, you can find here an example of the quartz.properties file I was using above
Check this article:
http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html
basically, set the taskExecutor property on SchedulerFactoryBean to use a org.springframework.scheduling.commonj.WorkManager TaskExecutor which will use container managed threads.
Just a note: the above QUARTZ-708's link is not valid anymore.
This new issue (in a new Jira) seems to be addressing the problem: http://jira.terracotta.org/jira/browse/QTZ-113 (fixVersion = 1.8.6, 2.0.2)
I have recently encountered this problem. Practically you need:
Implement thread pool by delegating work to Websphere Work Manager. (Quartz provides only SimpleThreadPool that run jobs on unmanaged threads). Tell quartz to use this thread pool by org.quartz.threadPool.class property
Tell quartz to use WorkManagerThreadExecutor (or implement custom one) by org.quartz.threadExecutor.class property
A bit patience with cumbersome legacy web containers :)
Here is github demo of using Quartz with Websphere (and also Tomcat).
Hope it helps someone..
You can check the below JIRA link raised on quartz regarding this.
http://jira.opensymphony.com/browse/QUARTZ-708
This has the required WebSphereThreadPool implementation which can be used with the changes in quartz.properties as mentioned to meet your requirements. Hope this helps.
Regards,
Siva
You will have to use websphere's managed thread pools. You can do this via spring and commonj. CommonJ can has a task executor that will create managed threads. You can even use a reference to a jndi managed thread resource. You can then inject the commonj task executor into the Spring based Quartz SchedulerFactoryBean.
Please see http://open.bekk.no/boss/spring-scheduling-in-websphere/ and scroll to "Quartz with CommonJ" section for more details.
The proposal from PaoloC for WAS85 ans Quartz 1.8.6 also works on WAS80 (and Quartz 1.8.6) and does not need Spring. (In my setup Spring 2.5.5 is present, but not in use in that context.)
That way I was able to override SimpleJobFactory by my own variant, using an InjectionHelper to apply CDI on every newly created job. Injection works for both #EJB (with JNDI lookup of the annotated EJB remote business interface) and #Inject (with JNDI lookup of the CDI BeanManager using a new InitialContext first, and then using this newly fetched BM to lookup the CDI bean itself).
Thank you PaoloC for that answer! (I hope this text will appear as an "answer to PaoloC" and not as an answer to the main topic. Found no way to differentiate between these.)