Jakarta EE 10 #Startup on K8S - java

Stack
Java
Jakarta EE 10
JBoss/Widlfly 27
Kubernetes K8S
JAX-RS (RestEasy)
I want to initialize some caches on startup of my app. During that time i want my readiness probe to respond not ready.
With the management inteface turned on, this works BUT not with my classes, instead the standard one responds.
Wildfly runs in standalone mode.
What i try to accomplish is to run my OWN code for readiness/live BUT that these endpoints are available during startup. I created my own outside of microprofile.healt but they are not available during startup.
Does anybody have some ideas?
Below is my code
import jakarta.enterprise.context.ApplicationScoped;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Liveness;
import org.eclipse.microprofile.health.Readiness;
/**
* Created by Gerry Askefalk on: 2023-01-13
*/
#ApplicationScoped
#Liveness
#Readiness
public class Mycheck implements HealthCheck {
#Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("mycheck").up().build();
}
}

Ok
the solution (and my bad) was to not add microprofile extensions to WF.
When i did, it works!
This article explained it to me.
microprofile on wf

Related

Invoking EJB 3.1 session Bean using remote standalone client

Although I have used EJB earlier, I want to re-assure myself that I understand how it really works.
So, I created a Simple Session Bean EJB (3.1), and packaged it as .ear (which has client jar as well). The below is the snippet:
Session Bean Implementation:
package com.example;
import javax.ejb.Stateless;
#Stateless
public class FirstSessionEJB implements FirstSessionEJBRemote {
public FirstSessionEJB() {
}
#Override
public String print() {
return "Hello";
}
}
Remote interface:
package com.example;
import javax.ejb.Remote;
#Remote
public interface FirstSessionEJBRemote {
public String print();
}
I deployed this EJB as .ear and it was successfully deployed in Wildfly 10.x.
Now, I want to access this using a standalone Java client, running in a separate JVM.
Here is the client code (It might not be completed as I am not clear on how to invoke mainly due to JNDI).
package com.example.main;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.example.FirstSessionEJBRemote;
public class Main {
public static void main(String[] args) throws NamingException {
String GLOBAL_JNDI_NAME="java:global/FirstEJBProjEAR/FirstEJBProj/FirstSessionEJB!com.example.FirstSessionEJBRemote";
Hashtable<String,String> jndiProperties = new Hashtable<>();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
InitialContext ic = new InitialContext(jndiProperties);
FirstSessionEJBRemote ejbRemote = null;
ejbRemote = (FirstSessionEJBRemote)ic.lookup(GLOBAL_JNDI_NAME);
ejbRemote.print();
}
}
I referred to this link on how to do the JNDI lookup (and what all parameters to use in, however it is not working.)
In the link it is mentioned that it has Wildfly specific jar which works without JNDI lookup.
Can anyone help me understand:
1) What all properties I need to set up for JNDI look up?
2) Is there any specific jar that needs to be present in client side application?
I don't want to use any specific Wildfly jar, that is, I want to go with traditional JNDI lookup, so can anyone please guide me on this?
It is very frustrating to struggle just to write a simple "Hello world" kind of EJB. I referred to some books are well, but all what they have provided is just the "lookup" code without actually telling what all properties needs to be included for JNDI and any jar to be included.
As the article you link to states albeit a bit hidden in that mountain of text, you do need the jboss-client.jar that you will find in the Wildfly server installation (bin/client/jboss-client.jar); it needs to be on the client's runtime classpath. It contains to begin with that org.jboss.ejb.client.naming package referenced in your code.
The jar contains the extra bit of magic for a client to be able to setup and maintain EJB remote invocations with the Wildfly server, just using JNDI isn't going to cut it. And there is no one jar to rule them all, each container (Wildfly, Glassfish, Weblogic, etc.) has its own implementation for a client library.
Do note that invoking EJBs from a client application is very old school (read: you don't want to do that). A more realistic and modern day view of EJB technology is to use it within an enterprise container itself, such as from a web application / war - say as part of a RESTful service. You likely don't even need the extra layer of the EAR file then, you can just package everything neatly into the one war application.
And in that scenario if you do have a client application, that client can talk to the RESTful service - a much simpler and cross-server, cross-platform communications interface.

#PostConstruct called twice on simple #Singleton #Startup bean

my problem is that the #PostConstruct is called twice even though it shouldn't. I searched a lot and found similiar problems with jersey https://java.net/jira/browse/JERSEY-1883?filter=-3. However I tried to make a small example which apparently still causes the problem even without any clatter.
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
#Singleton
#Startup
public class TestSingleton {
#PostConstruct
public void init() {
System.out.println("How many times am I being called?");
}
}
Configuration
Application server: Glassfish 3.1.2
Java Version: JDK 1.7_17
Packaging: A war file within an ear
Any ideas?
I figured it out by using #PreDestroy or Publish of the application server.
The problem is "normal". With using Eclipse as an IDE after the server start the application will be published again. Therefore you'll only see one log message of #PreDestroy but two of #PostConstruct.
The same goes for changing something and publishing afterwards. Here you should only see the message from #PostConstruct once.
Then you'll know everything is alright.
#PostConstruct —This is invoked immediately after a bean instance is created.
You can see this :
#Startup #Singleton instantiated twice in WebLogic (EJB 3.1)

EJB #Startup on Jetty

I need to make this code (that works with JBoss) run with Jetty:
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
import org.picketlink.idm.PartitionManager;
import org.picketlink.idm.model.basic.Realm;
#Startup
#Singleton
public class PicketLinkStartup {
#Inject
private PartitionManager partitionManager;
#PostConstruct
public void workaround() {
/*
* This forces the partition manager to be loaded on app startup. Without
* this, it is possible for a FailedAuthenticationException to leave
* picketlink in a bad state where the default partition is no longer
* accessible.
*/
partitionManager.getPartition(Realm.class, Realm.DEFAULT_REALM);
}
}
I need to have this PicketLinkStartup run at Jetty startup. Is there a way to do that?
JBoss is a full EE application server with an EJB container while Jetty is just a servlet container. To use session beans in your application you need to deploy into an EJB container.
You could try integrating OpenEJB with Jetty but no guarantee that it'll work.

New to EJB world... Null pointer exception in EJB client

I am learning EJB and I am trying to execute the Helloworld example given in EJB In Action book.
My app server is JBoss, I created the Jar file for the bean class and interface in the right directory( I can see the EJB in JMX console).
Now I created a simple client using EJB annotations, but I am getting a NullPointerException.
Here is my client code.
Client code:
package com.client;
import javax.ejb.EJB;
import com.EJB.*;
public class HelloWorldClient {
#EJB
private static HelloWorldInterface HelloBean;
public static void main(String[] args)
{
HelloBean.SayHelloWorldInEJB();
}
}
Bean class
package com.EJB;
import javax.ejb.Stateless;
#Stateless
public class HelloWorldBean implements HelloWorldInterface {
public void SayHelloWorldInEJB() {
// TODO Auto-generated method stub
System.out.println("Hello world from the world of EJB");
}
}
Interface
package com.EJB;
import javax.ejb.Local;;
#Local
public interface HelloWorldInterface {
public void SayHelloWorldInEJB();
}
Note: I tried using specifying the interface as Remote, it still didn't work.
Steps that I did so far to get to this point.
1) Created the file EJB files
2) Made the build.xml and deployed the EJB.
Am I missing any configuration files ???
Now I created a simple client using EJB annotations, but I am getting a NullPointerException.
Your client code looks like an Application Client and such client is supposed to be deployed on the app server and then executed in an Application Client Container (ACC) so that injection can occur. Starting the ACC requires an application server specific command.
The following wiki explains the usage of the ACC in JBoss (how to package, deploy and launch an ACC): How to use an application client in JBoss-5.
If you don't want to use an Application Client Container and instead just run the application client class through a java command, injection won't be possible and you'll have to perform a JNDI lookup.
And in both cases, you'll have to provide and use a remote business interface for your bean.
Resources
How to use an application client in JBoss-5
Creating and Running an Application Client on the GlassFish Server
Related questions
application-client
You would have to make two changes:
Replace the #EJB dependency injection with JNDI lookup. Dependency Injection is not supported for POJOs in EJB 3 (Don't know about EJB 3.1 though )
Then, the interface has to be a remote interface. The reason is that, the client here is a standalone java program - It would be running in JVM different from the web-app JVM.
Both dependency injection through #EJB and having the interface as #Local should work if the client was a servlet in the same server.

Mocking on the GAE development server?

I'm trying to mock an HTTPServletRequest data on my development GAE server. I'm running Eclipse Plugin 1.3.7
I've tried to do this:
package com.FOO.madservice.servlet.mock;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static org.mockito.Mockito.*;
#SuppressWarnings("serial")
public class BAR2ServletMock extends HttpServlet {
...
protected HttpServletRequest requestFilter(HttpServletRequest req) {
HttpServletRequest servletRequest = spy(req);
doReturn("gzip, deflate").when(servletRequest).getHeader("header-name-goes-here");
doReturn("174.30.216.4").when(servletRequest).getRemoteAddr();
return servletRequest;
}
...
}
Running the following gives exception:
java.lang.NoClassDefFoundError: sun.reflect.ReflectionFactory is a restricted class. Please see the Google App Engine developer's guide for more details.
Any ideas on how to disable class while list checking on GAE development server or perhaps using a different mocking library that works with GAE?
Thanks,
Maxim.
I doubt that you'll be able to get around this on the GAE.
The GAE is compliant with the Java Servlet Standard, so you could probably test out your program by installed a standard Java Servlet Container such as Tomcat.
Also, doesn't object mocking require reflection, by definition of "mocking"? The GAE whitelist is absolutely enforced, and you will not be able to get around it. To deploy on the app engine, there is no way to use the full reflection API (some classes are supported, however).

Categories