I have a Quarkus application that makes use of caches for methods.
These methods and cache eviction got to be tested somehow preferably when Quarkus context is fully operational.
This is what I figured (PostgresContainer for reference):
#QuarkusTest
class ScreeningRepositorySpec : PostgresContainer() {
private val cacheManager = CaffeineCacheSupplier().get()
init {
"test cache manager gets initialized" {
logger().info("Cache size: {}", cacheManager.size)
}
}
}
The problem arises when any kind of invocation happens for cacheManager: it fires NPE. https://github.com/im-infamou5/quarkus-cache-playground
Downstream code as follows is
#Override
public List<CaffeineCache> get() {
CacheManager cacheManager = cacheManager();
...
}
which ultimately yields:
public static CacheManager cacheManager() {
return Arc.container().instance(CacheManager.class).get();
}
And here comes that Arc.container() is null somehow.
What else was tried:
#QuarkusIntegrationTest - no bean for injection, null for arc container
Explicit #Inject for CacheManager - yields "no bean matches injection point"
Explicit Cache definition with manual CacheManager instantiation - same issue with null arc container
Variations for #Inject for default bean injection - same things about missing injection point
Looks like CacheManager bean lifecycle issue that expects it way too early and never succeeds as a result.
I've dug into quarkus tests which have quite a workaround but still hope easier approach is available to avoid this much dependensies just to test cache properly.
Version of Quarkus is 2.7.0.
Sample project can be found here with simple type of direct injection.
Output as follows:
org.acme.GreetingResourceIT > test cache size FAILED
kotlin.UninitializedPropertyAccessException at GreetingResourceIT.kt:11
Caused by: kotlin.UninitializedPropertyAccessException at GreetingResourceIT.kt:11
I am having issues with dependency injection in a batchlet.
#Named
public class SimpleBatchlet extends AbstractBatchlet {
#Inject
protected StorageService storageService;
...
public String process() throws Exception {
storageService.doSomething(); // this throws a null pointer exception
}
}
#Named
public class LocalFileStorageService implements StorageService {
public void doSomething() {
}
}
I have tried putting beans.xml in both META-INF and WEB-INF and removing it, all to no avail. I also tried changing the scopes of the beans to singletons, etc. I am invoking / starting the batch job through the use of an #Schedule annotation on a method that uses BatchRuntime to start the job.
I must be missing something simple as I know this should work. The actual scope of the beans I will use may need to vary, but the point I am trying to make is that I don't believe bean scope is a problem, but some other configuration issue.
I should also note that I only have 1 implementation of StorageService.
Not clear what really is your problem (NPE on injected CDI bean?), but annotating your Batchlet #Dependent should solve the problem :
#Named
#Dependent
public class SimpleBatchlet extends AbstractBatchlet {
#Inject
protected StorageService storageService;
}
Batchlet need to be #Named and #Dependent for integration with CDI.
I'm using Weblogic 12c, I need to run app before/with the web app starts.
the app should fetch information and write it to db.
I read that in previous versions of WL programmers used to work with ApplicationLifecycleListener, but it is deprecated now.
I'm compiling the project to ear file.
I also tried to use ejb3.2 eager singleton, but it didn't worked.
Is there any working alternative?
I solved the issue by creating EJB as the following:
#Singleton
#Startup
public class StartupBean {
#PostConstruct
private void startup() { ... }
#PreDestroy
private void shutdown() { ... }
...
}
Creating the EJB Singleton instances is one of the Weblogic life cycle init calls, I put my java code under startup() method.
I've got a problem exxh EJB's.
First of all, my setup: I am using GlassFish & JEE6. I have got a REST-Service packaged as a WAR and a bean packaged as an EJB-Jar. They are not inside an EAR.
The EJB should be used from the REST-WAR via #EJB, but when I try to deploy the WAR, GlassFish shows this error:
Error occurred during deployment:
Exception while deploying the app [exx-upload-1.0] : Cannot resolve reference Local ejb-ref name=com.ex.exx.model.FileUpload/ocr,Local 3.x interface =com.ex.exx.api.IOCRService,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session. Please see server.log for more details.
(The EJB was deployed before without any erros).
I have no clue why. Here is the EJB Code:
Interface:
#Local
public interface IOCRService {
public String performOCRonImage(BufferedImage input);
}
and Implementation:
#Stateless
#LocalBean
public class OCRScanner implements IOCRService {
private Logger logger = Logger.getLogger(this.getClass().getName());
private final static String NOT_RECOGNIZED = "Can not regocnize text";
/**
* Default constructor.
*/
public OCRScanner() {
logger.log(Level.INFO, "### OCR SCANNER BUILD" + this);
}
public String performOCRonImage(BufferedImage input) {
logger.log(Level.INFO, "### OCR SCANNER CALLED" + this);
}
...
And here is the important part in the WAR:
public class FileUpload {
private final File PROPERTIES_FILE = new File(
"fileUploadProperties.properties");
private final String PARAMETER_NAME = "file";
private final Logger logger = Logger.getLogger(this.getClass().getName());
#EJB
private IOCRService ocr;
public Response uploadFile(...) {
// do some stuff
logger.log(Level.INFO, "### EJB" + ocr.toString())
}
Anny suggestions? I can not find my failure here.
Solved this, by replaceing #Local with #Remote.
This works, however, I am not satisfied as I do not understand why.
Basically, given the specs (eg. explained in the tutorial), an application can only access other application's EJB, if they are decorated with #Remote.
Thus, you have 3 options:
decorate your EJB with #Remote (what you have done),
package both together inside an ear (as they would reside in the
same application then). But if you intent to deploy them in seperate
applications or even seperate servers, use 1.)
use CDI with #Inject, but this will still only discover the EJB if
either in the same application, or decorated as #Remote if not.
HTH,
Alex
You should not use #EJB if the target is not an EJB. I guess this is your case because you are trying to inject into a class in your WAR.
Instead use:
#Inject
private IOCRService ocr;
Basically, #Inject is better in most cases, because:
it is more typesafe,
it supports #Alternatives
it is aware of the scope of the injected object.
Another solution it's to add #Stateless(name=""), this worked form
We're using EJB3 on GlassFish v2.
My application includes a GenericServlet called StartupServlet, which has an init method. java.util.TimerTask pollers started from this method cannot lookup facades from the InitialContext.
However if I make an HTTP request and do a lookup, it succeeds. Therefore I have a workaround now where my poller startup code makes an HTTP connection to a page which looks up the interfaces they need.
How can I rearrange my application so I don't need to use such a hack? If possible the solution needs to work on GFv3 as well.
Thanks in advance for your help!
On GF 2, I have a servlet that on start ensures that my timer is created. This looks up a remote session bean and calls it successfully from the init() (not actual code, distilled down to the important parts):
#EJB(name="TimerSessionRef", beanInterface=TimerSessionRemote.class)
public class StartTimers extends HttpServlet {
#Override
public void init() throws ServletException {
super.init();
try {
Context ctx = new InitialContext();
TimerSessionRemote timerSession = (TimerSessionRemote) ctx.lookup("java:comp/env/TimerSessionRef");
timerSession.createTimer();
} catch (NamingException ex) {
logger.blah();
}