There is some confusion regarding the use of @Local and @Remote annotations and the use of interfaces generally in EJB 3 because of some flexibility in their use.
The purpose of this post is to clarify two related things:
1) Do you really need that interface for your EJB? Or just sometimes? When?
2) How do I solve the "Cannot resolve reference Unresolved Ejb-Ref" that I'm probably getting if I stumbled across this post? Might they be related?
In Glassfish, you can deploy and use an EJB with absolutely no interface whatsoever. It can back a Web Service, which you can invoke and use without issue. That's because you don't have any clients trying to invoke methods on your stubs.
So if you have a Session bean that you are _only_ using to back a Web Service, then I recommend that you _don't_ create an interface for it. The reason is that if you're going to the trouble of making a Web Service, you probably want people accessing it as a Web Service, and not trying to invoke it directly as if it were a regular EJB. Because reading is often harder than writing code, having unnecessary stuff around might just make things harder to maintain.
So that's one case in which you don't need the interface.
However, on a related matter, if you're using EJB 3, you may have seen this error during deployment: "Cannot resolve reference Unresolved Ejb-Ref"
Say you have this structure: an EAR that contains a WAR and an EJB-JAR. You even thought ahead and did the standard thing and put classes that both the EJB-JAR and the WAR will need (common models, exceptions, utility classes, whatever) in a "lib" directory off of the root in order to get your classloaders working properly. You made sure that you only have Web classes in your WAR (listeners, filters, servlets, etc, things that only work on the Web). You made sure you don't have any Web things in your EJB-JAR.
You made sure you _didn't_ just blindly copy shared classes all over your poor EAR like Tony Montana spraying an AK-47 full of utilities and domain models and exceptions into every possible deployment artifact and crossing your fingers hoping that the classloaders just magically work (uh, don't count on it--even if it works for a while).
So instead you put those things in the <EAR-ROOT>/lib directory. Perfect. And now that the EAR's "lib" directory is standardized (thank you very much, BEA, for APP-INF, which laid the groundwork for this long-overdue feature), you don't need references in your Manifest.MF files anymore--the classloaders will just pick everything up.
So you did all of this but you still have this error that you can't deploy because of this "Cannot resolve reference Unresolved Ejb-Ref".
This one might have you thinking that you need to restructure your Ant script in order to provide something like a client JAR that contains the interfaces (only--not the impls!) for your EJBs and put that in the Web tier. The answer is easier than that.
You might also be thinking that you need to modify your deployment descriptors and override something there--but if you're like me, you're just using annotations and you don't want to start mucking around with descriptors anymore. You definitely don't need to do that.
So here's what to do:
Just put this code in your servlet (or listener or filter (?!!) or whatever):
You do NOT have to specify the class, comme ca:
First thing is to make sure that you don't actually have any bean implementation classes anywhere in your WAR. That would be a Bad Thing. That violates all laws of enterprise classloaders, and I believe two minor laws of physics.
The solution is that you must have an interface for your EJB, even though they will compile and deploy and run a whole big important Web Service without one (see above).
Also, it doesn't matter if your interface contains your @Local or @Remote annotation or if your bean class does.
Many books and articles on EJB 3 show an interface that contains the @Local or @Remote annotation, but everything will work fine if you leave these annotations in your bean implementation class. This is preferable perhaps because it allows your interface to really be a true O-O interface. That is, to use the annotation in the interface destroys the purpose of interfaces in the first place, which is to define a contract, staying silent on implementation details; indicating that your interface is part of an EJB undermines this purpose precisely by revealing this dependency and coupling clients to it.
This is perhaps academic fussiness, because if your interface is no longer implemented by an EJB, it's no longer a managed resource and not a candidate for injection, and so your client will have to change _anyway_.
So I still come down on the side of "put your @Local annotation in your bean implementation and not your interface", for the simple sake of trying to focus on Thinking in Interfaces and not implementations.