EJB Injection failure on deploy

2019-08-21 18:09发布

问题:

I've got a problem exxh EJB's.

First of all, my setup: I am using GlassFish & JEE6. I 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.

回答1:

Solved this, by replaceing @Local with @Remote. This works, however, I am not satisfied as I do not understand why.



回答2:

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.


回答3:

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:

  1. decorate your EJB with @Remote (what you have done),
  2. 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.)
  3. 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



回答4:

Another solution it's to add @Stateless(name=""), this worked form