JBoss AS 7 - After Startup initialization - java

Is there any way to catch an event/implements a Class, or something like that, to detect that JBoss (AS7) is up and running and all applications has been deployed ?
I made a StartupServlet (which extends HttpServlet) because i need to call a local web service to initialize the system. But because my application is not fully deployed my call for the web service (in the StartupServlet) ends in a "404 Not Found error".
I tried to use a <listener>...</listener> on the web.xml but it's not working.

You can try using a Startup EJB, like explained here:
#Singleton
#Startup
public class StartupBean {
#PostConstruct
private void startup() { ... }
#PreDestroy
private void shutdown() { ... }
}
However the bean will not detect whether your applications are deployed, only that the current application - the one containing the bean - is deployed and started. Since the #PostConstruct method is called very early, you cannot rely on any other beans or services being available.
EDIT: Jboss also has a native management API. AFAIK it can also be used to query deployments. Unfortunately it's documentation is not really impressive, but perhaps you can figure it out.

According to my understanding, you do not need to detect when all application was deployed, you need to understand only if your application was deployed. To do it you should define ServletContextListener:
http://docs.oracle.com/javaee/5/api/javax/servlet/ServletContextListener.html#contextInitialized%28javax.servlet.ServletContextEvent%29
Than you can catch when it deployed:
public void contextInitialized(ServletContextEvent sce)
{
servletContext = sce.getServletContext();
}

Related

Inject of remote EJB interface into external module

I have an EAR application with three modules:
beans are in "app-ejb" module
remote interfaces are in "app-remote"
web services are in "app-war"
app-ejb and app-war use app-remote as library.
all are packaged in "app.ear".
This is working fine, but now I have to use the same beans outside the EAR application, and injection is not working.
I have in app-ejb:
#Stateless
#LocalBean
public class Services implements ServicesRemote {
[...]
}
and his remote interface in app-remote:
#Remote
public interface ServicesRemote {
[...]
}
In my app-war I can inject the remote bean without problem:
#Stateless
#LocalBean
public class UseServices {
#EJB
private ServicesRemote services;
[...]
}
Anyway in my external ejb application, deployed as stand-alone and using the same ejb-remote as library, if I try to inject the same EJB like this:
#Stateless
#LocalBean
public class UseServicesFromAnotherApp {
#EJB
private ServicesRemote services;
[...]
}
Glassfish (4.1) give me an error "Class [ Lcom/[...]/ServicesRemote; ] not found".
Is this expected? How can I inject the remote bean correctly?
Injection doesn't work with remote interfaces. Beans that are "injectable", live inside container's JVM and are available for injection to other beans inside the same application. The same holds true for accessing beans in another application in the same container, although applications may live in the same JVM. Since remote methods are originated from another JVM or another application, injection is not possible. You must use JNDI lookup instead to get a reference to a remote bean.
As a matter or personal taste, I would stay away from EJB Remote interfaces, and instead I would use another "remoting" technique such as REST.
The problem was probably generated by a number of hot deploys, made glassfish unstable.
When I restarted glassfish my code start to work properly (it's actually still working).
Sorry for posting here without trying to restart glassfish first.

EJB Injection in Application Client don't work

I tried inject a stateless EJB in my application client and I get the following error
SEVERE: Exception while preparing the app : Unable to load the EJB module. DeploymentContext does not contain any EJB. Check the archive to ensure correct packaging for C:\glassfish3\glassfish\domains\domain1\applications\EJB.
If you use EJB component annotations to define the EJB, and an ejb or web deployment descriptor is also used, please make sure that the deployment descriptor references a Java EE 5 or higher version schema, and that the metadata-complete attribute is not set to true, so the component annotations can be processed as expected
My client is defined thus:
#EJB
private static Sless sless;
public static void main(String[] args) {
System.out.println("Sless says: " + sless.hello());
}
The class Sless is my interface which is defined thus:
#Remote
public interface Sless {
public String hello();
}
I also have a class implementing Sless
#Stateless
public class SlessBean implements Sless{
#Override
public String hello() {
return "hello, world!\n";
}
}
Any help as to where the problem is coming from would be appreciated.
1) Standalone clients or non-managed POJOs(POJOs which are not maintained by Containers) do not support annotation injection. So #EJB will not work.
2) You will have to do a manual JNDI look up from your standalone client.
What you need for this ?
1) Your EJB extending Remote interface. Because Local interface does not expose EJB to Cross Application or Remote calls.
2) Dependency jar files in your standalone client. ie: ORB Jar
3) You will need to know RMI/IIOP port on your server.
4) You will also have to take care if Standalone client and Server use different JDK/JRE implementations. For ex: 1 using SUN JDK and other using IBM JDK.
Follow this for connecting to EJB on Glassfish from a Standalone client >> https://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB

Execute code after Glassfish Web Deployment [duplicate]

This question already has an answer here:
Using special auto start servlet to initialize on startup and share application data
(1 answer)
Closed 7 years ago.
I'm trying to run a java web service on Glassfish. There is some initialization code that sets a few variables and retrieves some information from the Glassfish environment itself.
I have that code in a static initializer inside the #WebService class, however this code appears to be called too early, it gets run as soon as the WebService endpoint is deployed, whereas I need it to run once the whole web service is successfully deployed.
I tried moving the code into the constructor of the WebService class, however then that code was only run when I went into the Tester web page and sent some data to make the web methods run.
Is there any way to set up some initialization code to be run as soon as the whole web service deployment is completed?
Option 1: In Glassfish you have the Lifecycle modules
Option 2:
You also have the ability to code a ServletContextListener to be triggered when the context is loaded:
public class MyServlet implements ServletContextListener {
public void contextInitialized(ServletContextEvent e) {
// implementation code
}
public void contextDestroyed(ServletContextEvent e) {
// implementation code
}
}
Reference:
About Life Cycle Modules
Example of ServletContextListener
Yes #Jaynathan Leung, with soapUI can you deployment the web services and testing your programming with input and output data. I hope help you. :)

Call EJB3 Local bean through Remote bean from external JVM

Not terribly experienced using EJB, and I ran into the following problem with which I hope one of you guys can help out.
Suppose the following situation: a set of #Local beans have been defined to provide access to a database. These beans are very simple, and are deployed on application server A (Weblogic 10.3.3). We want to provide access to these local beans via remote, and since we already have a "services" module set-up for providing external access to our services, our idea was to create a new #Remote service that uses the local beans described above (injected via #EJB). These service beans are also deployed on application server A. For example:
#Local
public interface DatabaseBeanLocal { doStuff(); }
#Stateless(name = "ejb/DatabaseBean", mappedName = "DatabaseBean")
public class DatabaseBean implements DatabaseBeanLocal { doStuff() { ... } ; }
#Remote
public interface ServiceBean { doSomeOtherStuff(); }
#Stateless
public class ServiceBeanImpl implements ServiceBean
{
#EJB(name = "ejb/DatabaseBean", mappedName = "DatabaseBean")
private DatabaseBeanLocal myDatabaseBean;
... methods etc. ...
}
The client that will actually use these remote beans is actually run on a different application server; application server B (also Weblogic 10.3.3). When we look-up the ServiceBean bean from our client, that works fine. When we call a method on it that needs access to DatabaseBean however, the call fails. The Weblogic server says it cannot find a bean for the DatabaseBean interface.
My questions: is this set-up even possible? In other words: will Weblogic (or another container) inject the local bean into the remote bean so that the client gets an instance of the remote bean that is capable of calling actions on the local bean (I assume not, but I'm asking anyway to be sure)?
If not, the I guess we'll have no other choice than to skip the service layer and provide direct access to the DatabaseBean example above via #Remote.
Update 1
After doing some tests, simply defining DatabaseBean above as #Remote rather than #Local "fixes" this issue. Ofcourse, this is not really a fix since this will call the DatabaseBean remotely, which is ridiculous because it's in the same module as the service. I'm starting to suspect that wrapping a local EJB with a remote EJB is simply not possible.
Update 2
What we've found so far:
We've not been able to manually inject the local EJB so far, because we cannot actually find it at runtime.
Weblogic apparently does not include local EJBs in the JNDI tree.
Calling the ServiceBean from outside the AS on which it is deployed still does not work, because the dependency on the local EJB is never resolved, or resolved client-side which means it's not found.
Local means local to EAR not to AS.
Your local and remote Beans must be in same EAR (not only in same AS). Are they?
-- edit --
Hmm.. If they're in the same EAR then it should work. I.e. answer to your question "is such a setup even possible?" is Yes.
Unfortunately now we're talking abt pure and simple debugging. First thing I would do is try and check if teh local bean (DatabaseBean I guess) is actually registered and working using WebPhere UTC equivalent in WebLogic (I never worked in WebLogic). I can list a 100 other things you can check for more logs/traces/symptoms but well, that's the way debugging goes.
Managed to get this issue resolved. the following configuration works for Weblogic 10.3.3 and allows for a remote EJB to use a local EJB, where the remote EJB can be called from anywhere.
Ultimately — after a lot of testing — the trick was apparently specifying a beanName value for the #EJB annotation used to mark the local bean as a dependency of the remote bean. Doh!
Deployment
#Local EJB is deployed on AS-A in EAR-1 (in its own module/JAR)
#Remote EJB is deployed on AS-A in EAR-1 (in its own module/JAR)
Client code that calls the remote service is deployed on AS-B in its own EAR archive
Annotations
The local EJB is a very simple and straightforward EJB bean, with the following interface and implementation:
#Local
public interface LocalBeanLocal {
// Implementation omitted
}
#Stateless(name = "LocalBean")
public class LocalBean implements LocalBeanLocal {
// Implementation omitted
}
The remote EJB is again a relatively simple EJB bean, except that it has a dependency on LocalBean. This dependency is expressed through the #EJB annotation; but it would seem that the beanName attribute is required for Weblogic to resolve this dependency correctly. Without the beanName attribute, calling the remote EJB would not work for us (in the sense that there would always be some kind of error when the local bean was involved)!
#Remote
public interface RemoteBeanRemote {
// Implementation omitted
}
#Stateless(name = "RemoteBean")
public class RemoteBean implements RemoteBeanRemote {
#EJB(beanName = "LocalBean")
private LocalBeanLocal localBean;
// Implementation omitted
}
What is apparently important here is that the beanName attribute in the remote service dependency declaration (#EJB(beanName = "LocalBean")) should have the same value as the bean name defined in the local bean implementation (#Stateless(name = "LocalBean")).
Lookup
Getting a reference to your remote EJB is done the traditional way, there doesn't seem to be a specific requirement. In our case, we look-up the remote service via JNDI.

Access ServletContext resources in CDI Extension

I'm facing the following situation: I have written a CDI extension, with which I want to programatically register additional beans into the BeanManager. I've already implemented the extension and registered in in the META-INF/services folder. Everything works fine so far and I can trace the container calling this method:
public class TestCdiExtension implements Extension {
public void observeAfterBeanDiscovery(#Observes AfterBeanDiscovery event, BeanManager manager) {
// Code goes here
}
}
My problem now is this: To determine which beans should be registered, I need access to the ServletContext of the current web application in which CDI is running.
I understand that you can use CDI completely without a servlet environment, so there is no hard link. However: How can I do the job of registering additional beans depending on what's in the ServletContext?
Is using an extension the correct way at all? Is there any other (better?) solution of doing this?

Categories