EJB를 JAX-RS (RESTful 서비스)에 삽입
주석을 통해 내 JAX-RS 웹 서비스에 Stateless EJB 를 삽입하려고합니다 . 불행히도 EJB는 정당 null
하고 NullPointerException
그것을 사용하려고 할 때 얻 습니다.
@Path("book")
public class BookResource {
@EJB
private BookEJB bookEJB;
public BookResource() {
}
@GET
@Produces("application/xml")
@Path("/{bookId}")
public Book getBookById(@PathParam("bookId") Integer id)
{
return bookEJB.findById(id);
}
}
내가 도대체 뭘 잘못하고있는 겁니까?
내 컴퓨터에 대한 몇 가지 정보는 다음과 같습니다.
- Glassfish 3.1
- 넷 빈스 6.9 RC 2
- 자바 EE 6
몇 가지 실제 사례를 보여줄 수 있습니까?
이것이 효과가 있는지 잘 모르겠습니다. 따라서 다음 중 하나입니다.
옵션 1 : 주입 공급자 SPI 사용
조회를 수행하고 EJB를 삽입 할 공급자를 구현합니다. 보다:
- @EJB 주입 .
com.sun.jersey : jersey-server : 1.17의 예 :
import com.sun.jersey.core.spi.component.ComponentContext;
import com.sun.jersey.core.spi.component.ComponentScope;
import com.sun.jersey.spi.inject.Injectable;
import com.sun.jersey.spi.inject.InjectableProvider;
import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.ws.rs.ext.Provider;
import java.lang.reflect.Type;
/**
* JAX-RS EJB Injection provider.
*/
@Provider
public class EJBProvider implements InjectableProvider<EJB, Type> {
public ComponentScope getScope() {
return ComponentScope.Singleton;
}
public Injectable getInjectable(ComponentContext cc, EJB ejb, Type t) {
if (!(t instanceof Class)) return null;
try {
Class c = (Class)t;
Context ic = new InitialContext();
final Object o = ic.lookup(c.getName());
return new Injectable<Object>() {
public Object getValue() {
return o;
}
};
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
옵션 2 : BookResource를 EJB로 만들기
@Stateless
@Path("book")
public class BookResource {
@EJB
private BookEJB bookEJB;
//...
}
보다:
옵션 3 : CDI 사용
@Path("book")
@RequestScoped
public class BookResource {
@Inject
private BookEJB bookEJB;
//...
}
보다:
이 스레드는 다소 오래되었지만 어제 같은 문제와 싸웠습니다. 내 해결책은 다음과 같습니다.
BookResource 를 클래스 수준에서 @ javax.annotation.ManagedBean 을 통해 관리 빈으로 만드십시오 .
이 작업을 수행하려면 beans.xml을 사용하여 CDI를 활성화해야합니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
BookResource가 war 파일의 일부인 경우이 파일은 WEB-INF에 있어야합니다. BookResource가 ejbs와 함께 패키지 된 경우 META-INF에 넣습니다.
@EJB를 사용하려면 완료되었습니다. @Inject를 통해 EJB를 주입하려면 beans.xml을 ejbs jar 파일에 META-INF로 넣어야합니다.
수행중인 작업 : 리소스가 컨테이너로 관리되어야한다고 컨테이너에 알리는 것입니다. 따라서 주입 및 수명주기 이벤트를 지원합니다. 따라서 EJB로 홍보하지 않고도 비즈니스 파사드를 갖게됩니다.
You don't need to extend javax.ws.rs.core.Application for this to work. BookResource is as a root resource automatically request scoped.
Tested with Glassfish 3.1.2 and a maven project.
Happy coding.
You shall be able to do injection in JAX-RS resource without making it EJB or CDI component. But you have to remember that your JAX-RS resource must not be singleton.
So, you setup your application with this code. This makes BookResource class per-request JAX-RS resource.
@javax.ws.rs.ApplicationPath("application")
public class InjectionApplication extends javax.ws.rs.core.Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public InjectionApplication() {
// no instance is created, just class is listed
classes.add(BookResource.class);
}
@Override
public Set<Class<?>> getClasses() {
return classes;
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}
With this setup, you are letting JAX-RS to instantiate BookResource for you on per-request basis and also inject all the required dependencies. If you make BookResource class singleton JAX-RS resource, this is, you put in getSingletons
public Set<Object> getSingletons() {
singletons.add(new BookResource());
return singletons;
}
then, you created instance which is not managed by JAX-RS runtime and nobody in container cares to inject anything.
Unfortunately, my answer is too long for a comment, so here goes. :)
Zeck, I hope that you are aware of what exactly you are doing by promoting your bean to an EJB, as suggested by Pascal. Unfortunately, as easy as it is nowadays with Java EE to 'make a class an EJB', you should be aware of the implications of doing so. Each EJB creates overhead along with the additional functionality it provides: they are transaction aware, have their own contexts, they take part in the full EJB life cycle, etc.
What I think you should be doing for a clean and reusable approach is this: extract the access to your servers services (which hopefully are accessed through a SessionFacade :) into a BusinessDelegate. This delegate should be using some kind of JNDI lookup (probably a ServiceLocator - yes, they are still valid in Java EE!) to access your backend.
Okay, off the record: if you really, really, really need the injection because you do not want to write JNDI access manually, you could still make your delegate an EJB, although it ... well, it just feels wrong. :) That way at least it will be easy to replace it later with something else if you do decide to switch to a JNDI lookup approach...
I was trying to do the exact same thing. I'm using EJB 3.1 and have a deployed my app as an EAR with separate EJB project. As Jav_Rock pointed out, I use context lookup.
@Path("book")
public class BookResource {
@EJB
BookEJB bookEJB;
public BookResource() {
try {
String lookupName = "java:global/my_app/my_ejb_module/BookEJB";
bookEJB = (BookEJB) InitialContext.doLookup(lookupName);
} catch (NamingException e) {
e.printStackTrace();
}
}
@GET
@Produces("application/xml")
@Path("/{bookId}")
public Book getBookById(@PathParam("bookId") Integer id) {
return bookEJB.findById(id);
}
}
See the link below for very useful JNDI look up tips
Arjan is right. I created another class to initialize the EJB instead of creating a bean for RS
@Singleton
@LocalBean
public class Mediator {
@EJB
DatabaseInterface databaseFacade;
to avoid null pointer with:
@Path("stock")
public class StockResource {
@EJB
DatabaseInterface databaseFacade;
...
it actually works on GF
I have the same problem, and I solved it calling te EJB by a context lookup (the injection was impossible, I had the same error NullPointerException).
참고URL : https://stackoverflow.com/questions/3027834/inject-an-ejb-into-jax-rs-restful-service
'program tip' 카테고리의 다른 글
클래스에 정적 필드와 메서드 만있는 것이 나쁜 습관입니까? (0) | 2020.11.01 |
---|---|
PHP에서 배열 요소를 문자열로 캐스팅하는 방법은 무엇입니까? (0) | 2020.11.01 |
Python에서 파일 끝에 함수 선언 (0) | 2020.11.01 |
junit의 java.lang.NoClassDefFoundError (0) | 2020.11.01 |
마르코프 체인 챗봇은 어떻게 작동합니까? (0) | 2020.11.01 |