EJB Injection failure on deploy - glassfish

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

Related

Inject EJB into JAX-RS 2.0 subresource when subresource is got via ResourceContext

I am using Jersey 2.8 with Glassfish 4.0.
I have a resource locator class which looks like below
#Path("/")
#ManagedBean
public class MyServiceLocator {
#Context
ResourceContext rc;//javax.ws.rs.container.ResourceContext
#EJB
private MyEJBHome myEJB;
#Inject//javax.inject.Inject
MySubService mss;
#Path("/mysubservice")
public MySubService getMySubService() {
return rc.getResource(MySubService.class);
//also tried return rc.initResource(new MySubService());
}
}
and a sub resource class which is
#ManagedBean
public class MySubService {
#EJB
public MyEJBHome myEJB;
#Context
HttpHeaders heads;
/*#Inject
private myEJBHome myEJB2;*/
#Path("/mypath")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Object doSomething(#Context SecurityContext securityContext) {...}
}
beans.xml file is put to META-INF and WEB-INF.
In MyServiceLocator class private MyEJBHome myEJB is injected successfully. And MySubService mss object is injected successfully and with EJB injected into it.
The problem is that when MySubService is got via ResourceContext the EJB is not injected into it.
Previously i used Glassfish 3 and Jersey 1.17 with proprietary ResourceContext and absolutely the same code worked ok.
I googled a lot and read a lot of similar (but a bit different) questions and as i understood non JAX-RS stuff (EJB in my case) can't be injected when sub resource is got via ResorceContext. Is it true? If yes how can i work it around?
The one possible solution is to inject sub resource objects to the resource locator class but there are too many of them and it seems to be very ugly.
EDIT Injection with #Inject works if to create a binder, bind ejb class to ejb interface and register that binder. But i don't want to describe binding for hundreds of my ejbs. Also as i understand it is specific binding fir HK2 system and i don't want to be linked to it.
Different actions with setting #Named annotations and trying to inject via CDI didn't help. It seems that when getting sub-resource via ResourceContext Jersey uses only HK2 and that's why CDI can't do it's work. Is that correct?
The only appropriate solution i found was to create my own annotation and inject provider.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface EJBInject {
String beanName();
}
#Provider
public class EjbInjectProvider implements InjectionResolver<EJBInject> {
#Override
public Object resolve(Injectee injectee, ServiceHandle<?> handle) {
try {
String beanName = injectee.getParent().getAnnotation(EJBInject.class).beanName();
return new InitialContext().lookup("java:global/MyApp/" + beanName);
} catch (Exception e) {
return null;
}
}
#Override
public boolean isConstructorParameterIndicator() {
return false;
}
#Override
public boolean isMethodParameterIndicator() {
return false;
}
}
Then ejb can be injected using that annotation like
#EJBInject(beanName="MyBean")
MyBeanEJBHome myBean;
In such case any standard EJB injections which MyBeanEJBHome might need work correctly, too.

NullPointerException and #EJB

I use EJB3+JavaEE6+JBoss. I am absolutely newbie in EJB. I wrote this code:
package server.ejb;
#Remote
public interface HelloUser
{
void sayHello( String name );
}
#Stateless
public class HelloUserBean implements HelloUser
{
#Override public void sayHello( String name )
{
System.out.println( "Hello " + name );
}
}
Having assebled this code with Maven and deployed it on JBoss, I wrote a client:
import server.ejb.HelloUserBean;
import javax.ejb.EJB;
public class Test
{
#EJB
public static HelloUserBean bean;
public static void main( String... args )
{
bean.sayHello( "Alex" );
}
}
After compiling, I've got NullPointerException. It said that bean was null. Using JDNI + PersistentContext I could get a success, but I still can't use DI as well. Please, help me
I reorginized my code! Actually I wrote another server-side project with the same sence and a standalone client-app. Here is the structure of server-side app:
#Remote
public interface EchoRemote{
String getMessage();
}
#Stateless
public class EchoBean implements EchoRemote{
#Override
public String getMessage(){
return "Hello From Stateless Bean";
}
}
public class InvokationClient{
#EJB
private EchoRemote bean;
public String getMessage(){
return bean.getMessage();
}
}
And here is the client-side standalone app:
import com.steeplesoft.client.InvokationClient;
public class Main{
public static void main( String... args ) throws IOException{
InvokationClient client = new InvokationClient();
FileWriter fileWriter = new FileWriter( "D:/invokation_client_test.txt" );
fileWriter.write( client.getMessage() );
fileWriter.close();
}
}
I've got empty file and NullPointerEception in console
I hope you can help me :) It's tremendously important for me!!!
So you start your Test-class standalone in a separate JVM. Where did you configure to which JBoss it should connect? Which component does the dependency injection? Since you don't have a DI container that manages the Test-class and since the connection to JBoss is not configured anywhere, this can't work.
In order to make it work, you can do the following:
1) Write a Servlet, use #EJB in the Servlet and deploy it on JBoss. Put your EJB and the Servlet in the same WAR to make it easy. The Servlet is managed by the container and DI works. As a newbie with EJB I would do this first.
2) Do a JNDI-Lookup and call your EJB from a standalone client as described in https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI
3) Use an Application Client Container (ACC) as described in http://blogs.steeplesoft.com/posts/2011/02/22/java-ees-buried-treasure-the-application-client-container/ Deploy the EAR to jboss and invoke the client locally
$JBOSS_HOME/bin/appclient.sh --host remote://localhost:4447 ./local/path/to/enterpriseapplication-0.1-SNAPSHOT.ear#appclient-0.1-SNAPSHOT.jar
Remark: When I tried the example from blogs.steeplesoft.com, I had problems with the Swing classes, but it did work JBoss EAP 6.2, when I removed the Swing classes.

An EJB is in a JAR but is not found by the WAR next to in in an EAR

I have the structure described below, but I cannot make it so MyWebService has its member myService not null. The code of MyWebService is properly executed when I call the webservice. When I look at the JBoss logs, I keep seeing that MyServiceBean has several JNDI bindings allocated to it.
So how do I bind MyServiceBean to MyWebService?
Thanks!
my-ejb.jar:
#Local
public interface MyServiceBeanLocal {
...
}
#Stateless
public class MyServiceBean implements MyServiceBeanLocal {
...
}
my-web.war:
#Webservice(...)
public class MyWebService {
#EJB
MyServiceBeanLocal myService;
...
}
my-ear.ear:
* my-ear.ear
|-* my-web.war
|-* my-ejb.jar
Have you tried using MyServiceBeanLocal as a Remote interface ? You are trying to use dependency injection from a Web module and for a Local Interface .This is not actually suggested. Anyway, At first try to make the interface #Remote . If still it doesn't work try to use`Remote Look up from the Web module for your Remote interface link
I use CXF. CXF is not an EJB container, hence the issues I got.
I had to manually bind the EJBs, using their full name.

Dozer DozerBeanMapper Instantiation Startup EJB App Server Glassfish

Dozer's documentation states that you should only have one instance of DozerBeanMapper running in the app on the server. For initial development I ignored this, now I want to update the app to do this.
How can I instantiate the DozerBeanMapper class when the application starts on glassfish, and how would I access its "map" method in another class once the application has started or been newly deployed?
This is for EJBs so I can't use any servlet to do this.
OK, so I've finally had time to refactor this code. With the pointer from #Mikko Maunu, I am editing my question to provide the code that I have working for me for anyone who might find it useful in the future.
package com.xyz.utilities.singleton;
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import org.dozer.DozerBeanMapper;
#Startup
#Singleton
public class DozerInstantiator {
private DozerBeanMapper mapper = null;
#PostConstruct
void init() {
mapper = new DozerBeanMapper();
}
public DozerBeanMapper getMapper() {
return mapper;
}
}
And here is a straight forward usecase:
Inject an EJB member variable to your client class:
#EJB
DozerInstantiator di;
Within a method somewhere in the client class you can invoke the dozer mapper like so:
Credentials credentials = di.getMapper().map(credentialsDTO, Credentials.class);
// or
Credentials credentials = new Credentials();
di.getMapper().map(credentialsDTO, credentials);
If this is wrong or off base, someone please leave a comment. Until then, this seems to work so I'll use this solution I've developed with Mikko's input.
If you are using GlassFish 3.x, then you can use EJB 3.1 Singleton Session Bean:
#Startup //initialization in application startup
#Singleton //only one instance
public class DozerInitializer {
private String status;
#PostConstruct //executed once and only once when sole instance is created
void init {
//do steps needed to instantiate DozerBeanMapper
//here
}
}

Annotation JCacheResult is not working in Infinispan and Glassfish 3.1.1

I am trying to integrate JCache from Infinispan into my existing EJB project.
I have added Infinispan 5.0.1 CDI and Core packages to Maven pom.
Added Infinispan Interceptors in beans.xml and able to use the CacheResult annotation.
I am deploying the app in Glassfish 3.1.1. I have checked the Weld jar version, which is
Module : org.jboss.weld.osgi-bundle:1.1.1.Final
In the runtime, the CacheResult Method interceptor is not caching the method result and its always called.
My code looks like this,
public void cacheTest() {
Thread.currentThread().setContextClassLoader(
this.getClass().getClassLoader());
EmbeddedCacheManager manager = createCacheConfig();
Set<String> cacheList = manager.getCacheNames(); // new
// DefaultCacheManager().getCacheNames();
for (String cache : cacheList) {
System.out.println("Cache name " + cache);
}
defaultCache = manager.getCache("test-cache");
defaultCache.put("aa", "AA");
String user = "User";
greet(user);
Set<String> keys = defaultCache.keySet();
for (String key : keys) {
System.out.println("Key is -" + key + "Value is -"
+ defaultCache.get(key));
}
}
#CacheResult(cacheName = "test-cache")
public String greet(#CacheKeyParam String user) {
user += "Hello";
return user;
}
public EmbeddedCacheManager createCacheConfig() {
EmbeddedCacheManager manager = new DefaultCacheManager();
Configuration conf = new Configuration();
conf.fluent().eviction().strategy(EvictionStrategy.FIFO).maxEntries(10)
.expiration().maxIdle(1200000L).build();
conf.fluent().clustering().sync();
manager.start();
manager.defineConfiguration("test-cache", conf);
return manager;
}
greet() method gets called but it will never add the method result to the test-cache. I feel am I missing some configuration or...I dont know. Please help me on this.
when I Inject the classes, they wont get constructed and they are null. The code is like this,
#Inject
private static org.infinispan.Cache<String, String> defaultCache;
#Inject
private static EmbeddedCacheManager defaultCacheManager;
These gets executed without any error, but they wont get initialized.
I have no clue...But I am able to inject other EJBs with in this class easily. By the way I am trying to add Jcache functionality in one of EJBs.
I would appreciate your help...
Thanks...
Raj S
Your greet method is in a CDI bean or in an EJB, right?
The cache defined in JCache annotations is looked up in the cache manager provided by Infinispan CDI. This cache manager contains the cache configured with CDI (for more information, see https://docs.jboss.org/author/display/ISPN/CDI+Support). In your example the test-cache configuration will have no effect.
Another thing, if your cacheTest and greet methods are in the same class the greet method cannot be intercepted. If that's not the case maybe you're hitting GLASSFISH-17184.
For the Cache and EmbeddedCacheManager injections the problem is that you're doing a static injection, not supported by CDI. From CDI (JSR-299) specification
An injected field is a non-static, non-final field of a bean class, or of any Java EE component class supporting injection.
If your method result is not cached, I think it's because the CacheResultInterceptor is not called. I've just made the test with the Infinispan CDI quickstart. If the interceptors are in a lib they are not enabled. I think it's a bug in Glassfish.
Btw, you can see an example of code in the Infinispan CDI quickstart here.
Hope this help!