I'm new to EJB. I have an ejb-jar file which contains, "Class1" and i deployed it to glassfish server. Now there is another jar file which contains only the following client file(it has a dependencey injection), so my problem is how should i execute this file?
I just deployed it to glassfish, but it doesn't work and show error in log file("it contains zero ejb").
import com.pack.Class1;
public class CreateAccoutnClient {
#EJB
private static Class1 class1;
public
static void main(String[] args) {
}
}
If anyone who have read EJB 3 in Action, i'm tring to deploy chapter3 code to glassfish with eclipse.
Thanks :)
EJB context doesn't execute any main methods, with Glassfish (and others) you must deploy a war to have entry points that run your app or methods (web services or web app).
A jar can contain MDB, remote ejbs or scheduled timers, or could be just a library. The only way to execute some initialization method at startup is to use the EJB3 #Startup annotation
Related
I have six Java Scheduler classes, each with a different purpose but all coded in the same way. Only three of these are triggering on my WebSphere Application Server installation.
Interface:
import javax.ejb.Local;
#Local
public interface IScheduledProcessorBean
{
public void doProcessing();
}
Implementations (an example of one that isn't working, but all six are identical except for naming):
#Stateless
#HousekeepingProcessor
public class HousekeepingTimer implements IScheduledProcessorBean
{
public static final String className = "HousekeepingTimer";
#PersistenceContext(unitName = "WOTISEJB")
private EntityManager em;
/**
* Default constructor.
*/
public HousekeepingTimer()
{
// Default Constructor
}
// Try not to clash with the other schedule timer flows.
#Schedule(minute="20", hour="8-20", dayOfWeek="Mon-Fri",
dayOfMonth="*", month="*", year="*", info="HousekeepingTimer", persistent=true)
public void doProcessing()
{
Logger.getGlobal().fine(()->className + " called at: " + new java.util.Date());
try
{
// Specific logic goes here
}
catch (Exception e)
{
Logger.getGlobal().log(Level.SEVERE, "Scheduler failed for Housekeeping", e);
}
}
}
Processor Annotation:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public #interface HousekeepingProcessor {
}
Each of the six timers follow the exact pattern above, however only three of them trigger.
In the WebSphere Application Server 9 Console, under Enterprise Applications -> Application -> EJB JNDI names, In only see three of the Beans (the three that run successfully), and not all six.
Likewise under Enterprise Applications -> Application -> Binding enterprise Bean with business interface to JNDI names I only see the three working schedulers.
And, likewise, when installing the application, the "Provide JNDI names for beans" and "Bind EJB Business" steps of the detailed installation path only show those same three beans.
When I look in ejb-jar_merged.xml in the deployed files, again, only the three working timers are there.
I have tried creating ejb-jar.xml and deploying it explicitly, and that works - so there's something in Websphere's automatic bean processing that isn't picking it up without a prompt.
Can anyone suggest what might be going on here?
It looks like the three out of six Scheduler classes are not triggering in WebSphere Application Server. This is likely due to a problem with the EJB JNDI names not being bound correctly to the Scheduler classes.
Here are a few steps to troubleshoot this issue:
Confirm that all six Scheduler classes are included in the
deployment unit (e.g. .ear file).
Check that the #Stateless annotation is present on all six Scheduler
classes.
Verify that there are no classpath or package level issues that
prevent the Scheduler classes from being detected during deployment.
Make sure that the Maven dependencies, if applicable, are properly
configured in the project's pom.xml file.
Ensure that all Scheduler classes have a default constructor.
The fact that the EJB is not bound in JNDI indicates WebSphere does not recognize the class as an EJB. Since things work when using an ejb-jar.xml file, that suggests the EJB class is at least on the classpath for the application.
Here are some additional troubleshooting steps:
1 - Confirm the EJB class is packaged in one of the following locations:
a) in a .jar file at the root of the .ear file, b) in a .jar file in the WEB-INF/lib directory of a .war file, c) in the WEB-INF/classes directory in a .war file. Only these locations will be scanned for EJB component defining annotations (as required by the EJB specification).
2 - If an application.xml file is present, ensure the version is >= 5.0. If the EJB is packaged in a .war file, ensure the web.xml file version is >= 2.5. (and ejb-jar.xml >= 3.0)
3 - Confirm the import for the #Stateless annotation is javax.ejb.Stateless (and not jakarta.ejb.Stateless).
4 - Confirm the javax.ejb.Stateless annotation class is not packaged in the application or included on the application classpath. WebSphere provides the EJB API classes and there could be a conflict if the application also includes a copy.
5 - Look for any warnings in the log that indicate there was a problem accessing annotations for the application. Possibly a message starting with CWMDF. For example, CWMDF0022W: An attempt to scan class file "{0}" in JAR file "{1}" failed with exception: "{2}".
6 - Confirm the ejb-jar.xml file does not include metadata-complete="true". Granted, it sounds like you started without an ejb-jar.xml file, but WebSphere does support an option during application install to generate an ejb-jar.xml file and mark it metadata-complete. Ensure you do not use this option at least for troubleshooting purposes.
I have an EJB deployed in an EAR:
#Stateless
#Remote(ActorProvider.class)
public class ActorServiceClient implements Serializable, ActorProvider { ... }
Here is the remote interface:
#Remote
public interface ActorProvider { ... }
Now, I have a separate WAR being deployed with the following class:
#Singleton
#Startup
public class ShiroStartup implements IShiroStartup {
#EJB
ActorProvider actorProvider;
...
}
The idea being that I deploy my actor service in an EAR, and I separately deploy a client project that gets the ActorProvider which Shiro uses for authorization (this is ancillary, but what I'm using it for).
I get an error starting the ShiroStartup (after I have deployed the EAR with the provider in it):
No EJB found with interface of type 'consumers.ActorProvider' for binding realm.ShiroStartup/actorProvider
Why can't I do this? If I put the Provider in the war with the ShiroStartup it works fine, but it will not inject across deployments. Why is that? This is Wildfly 9 using JavaEE 7.
1., The EJB and WAR modules should take place in the same EAR
or
2., Include the EJB jar into the classpath of the WAR
or :)
3., with portable JNDI names (for remote interfaces):
https://docs.oracle.com/cd/E19798-01/821-1841/girgn/index.html
In particular: java:app[/module name]/enterprise bean name[/interface name]
I have two distinct archives within in the same .ear deployed on an application server. One is a .war and one is a .jar. I have the same package names in both archives
in .jar archive>> com.me.dummy.MyClass
in .war archive>> com.me.dummy.CLientClass
In com.me.dummy.MyClass I have a protected method called proctectedMethod() . In com.me.dummy.CLientClass i invoke com.me.dummy.MyClass.proctectedMethod().
This does not cause any compile time issues, but at runtime it throws accessError
java.lang.IllegalAccessError
Why does this only throw the IllegalAccessError at runtime?
Thanks
I believe that this happens because your application server loads web application using separate class loader. You should consult your app server documentation how to make it to use the same class loader for whole enterprise application.
I have Tomcat 7.0.47 and I'm hosting a REST Easy JAXRS service. The service uses two external JARs, one that has a base repository interface and default implementation and one that creates a concrete repository derived from the base (i.e. these two JARs have a dependency).
The service works, i.e. I can send a request and get back data from the database.
Now what I'm trying to do is get the repository injected into the REST service, to do this I've changed the REST code to look like
#Path("/country")
public class CountryService {
#Inject
ICountriesRepository repository;
#GET
#Produces({"application/json", "application/xml"})
public List<Country> getCountries() throws NamingException, SQLException {
return repository.getCountries();
}
}
I've added a beans.xml file to the web application's WAR file (it's in the META-INF directory) and I've added beans.xml to both the JARS.
When I deploy the app I see the following message:
INFO: Adding scanned resource: com.mantiso.cricket.service.CountryService
but I don't see similar messages for the repository class in the JAR.
The JAR is deployed; the beans.xml file is in the JAR's META-INF directory; I've tried adding #ManagedBean to the repository class.
I'm sure I'm missing something simple, but lots of searching has turned up not a lot.
This is Tomcat 7.0.47; Weld 2.1.0; RESTEasy 3.0.5
What else should I try?
And the answer is: The beans.xml file for the web app must be in the WEB-INF directory. If it's in the META-INF directory then it's not parsed.
Although, this did appear to work OK when I tried injecting into a servlet
I am using Glassfish 4. And I have an EAR which has a WAR and a JAR (with the EJBs).
I want to call the EJBs from my WAR but am not really sure if I need to use Local or Remote interfaces.
Inside my JAR, my Bean looks like this :
#Stateless
public class Test implements TestLocal {
#Override
public void testing() {
}
}
And my local :
#Local
public interface TestLocal {
void testing();
}
Inside my WAR I have a web service and it looks like this :
#WebService(serviceName = "TestWS")
public class TestWS {
private #EJB TestLocal testBean;
#WebMethod(operationName = "test")
public String test() {
testBean.test();
}
}
Both of these are packaged into an EAR.
When I call my WebService method I get an AccessLocalException :
Warnung: javax.ejb.AccessLocalException: Client not authorized for
this invocation at
com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1895)
at
com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:210)
Firstly :
Is this the correct way to call the EJB. Can a WAR inside an EAR use Local interfaces from an included JAR?
If so then does anyone know what I am doing wrong? Do I need to setup some kind of security configuration?
To look up a remote EJB, it must have a remote interface exposed. Include that remote interface into your war.
The GlassFish documentation has an entry for this error:
javax.ejb.AccessLocalException: Client Not Authorized Error
Description
Role-mapping information is available in Sun-specific XML (for example, sun-ejb-jar.xml), and authentication is okay, but the following error message is displayed:
[...INFO|sun-appserver-pe8.0|javax.enterprise.system.container.ejb|...|
javax.ejb.AccessLocalException: Client not authorized for this invocation.
at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:...
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(...)
Solution
Check whether the EJB module (.jar) or web module (.war) is packaged in an application (.ear) and does not have role-mapping information in application level, Sun-specific, sun-application.xml. For any application (.ear), security role-mapping information must be specified in sun-application.xml. It is acceptable to have both module-level XML and application-level XML.
#Remote is usefull if you deploy separately your jar which contain your EJBs on a different server, for example.
There, war and jar are in the same ear so you just have to use the Local annotation.
Tips : since EJB 3.1 interfaces are not required, you can use #LocalBean directly on your "Test" class and remove the TestLocal interface.
To call a ejb method into a class which is your war, you firstly have to create a link between war and jar. Being in the same ear is not enough.
If you use Maven, you can simply add the jar reference into your dependencies in the pom of your war.