2011-11-29 4 views
1

JavaEE (서버 측) 부분 JavaSE (클라이언트 측)의 일부인 응용 프로그램이 있습니다. 클라이언트의 아키텍처가 잘되기를 원하기 때문에 다양한 구성 요소를 주입하기 위해 Weld를 사용합니다. 이러한 구성 요소 중 일부는 서버 측 @EJB이어야합니다.Welding의 주입 주석으로 @EJB 사용

Weld가 Weld 아키텍처를 확장하여 클라이언트가 참조하려고 할 때 Weld가 JNDI 조회를 수행하여 EJB의 인스턴스를로드 할 수있게하는 "구성 요소"를 제공하는 것이 계획입니다. 그러나 나는 그것을 어떻게합니까? 다른 worrds에서

는 I 서버 측에서 클라이언트 측

public class ClientCode { 
    public @Inject @EJB MyEJBInterface; 
} 

가지고 싶어

용접부
@Stateless 
public class MyEJB implements MyEJBInterface { 
} 

"묵시적"는 JNDI 룩업 때 ClientCode 수행 개체가 만들어집니다. 어떻게해야합니까?

답변

3

기본적으로 그렇게하려면 portable CDI extension이라고해야합니다.

그러나 길기 때문에 약간의 조정이 필요하므로 더 자세히 설명하겠습니다. 용접 문서가 설명처럼

휴대용 확장

은, 첫 번째 단계는 하나의 흥미로운 CDI 이벤트에 해당하는 코드를 작성하는 것입니다있는 Extension 태그 인터페이스를 구현하는 클래스를 만드는 것입니다. 그 정확한 경우, 가장 흥미로운 사건은 내 마음에, AfterBeanDiscovery입니다. 실제로이 이벤트는 CDI impl에 의해 모든 "local"bean이 발견 된 후에 발생합니다.

그래서, 확장을 작성하는 것은 더 적은 OPR이며, 해당 이벤트에 대한 처리기를 작성 :

public void loadJndiBeansFromServer(
     @Observes AfterBeanDiscovery beanDiscovery, BeanManager beanManager) 
     throws NamingException, ClassNotFoundException, IOException { 
    // Due to my inability to navigate in server JNDI naming (a weird issue in Glassfish naming) 
    // This props maps interface class to JNDI name for its server-side 
    Properties interfacesToNames = extractInterfacesToNames(); 

    // JNDI properties 
    Properties jndiProperties = new Properties(); 
    Context context = new InitialContext(); 
    for (Entry<?, ?> entry : interfacesToNames.entrySet()) { 
     String interfaceName = entry.getKey().toString(); 
     Class<?> interfaceClass = Class.forName(interfaceName); 
     String jndiName = entry.getValue().toString(); 
     Bean<?> jndiBean = createJndIBeanFor(beanManager, interfaceClass, jndiName, jndiProperties); 
     beanDiscovery.addBean(jndiBean); 
    } 
} 

빈을 만들기 사소한 작동되지 않습니다 : 더 고급 용접에 "기본"자바 반사 객체를 전달해야합니다 것들 (글쎄, 내 경우에는)

private <Type> Bean<Type> createJndIBeanFor(BeanManager beanManager, Class<Type> interfaceClass, 
     String jndiName, Properties p) { 
    AnnotatedType<Type> annotatedType = beanManager 
      .createAnnotatedType(interfaceClass); 
    // Creating injection target in a classical way will fail, as interfaceClass is the interface of an EJB 
    JndiBean<Type> beanToAdd = new JndiBean<Type>(interfaceClass, jndiName, p); 
    return beanToAdd; 
} 

마지막으로 JndiBean 클래스를 작성해야합니다. 그러나 전에는 주석 영역에서 약간의 이동이 필요합니다.

이 사용 된 주석 처음에는

정의, 나는 @EJB 하나를 데 사용합니다. A 불량 아이디어 : Weld는 bean의 해시 코드를 빌드하기 위해 qualifier annotation 메소드를 사용하여 결과를 호출합니다! 그래서, 나는 자신의 @JndiClient 어노테이션을 만들었는데, 어노테이션은 아무런 방법도없고, 상수도 아니기 때문에 가능한 한 간단 해졌습니다.

두 개념이 여기에 병합 JNDI를 클라이언트 빈을 구축.

  • 한편, Bean 인터페이스는 콩이 무엇인지 정의하는 것처럼 보입니다. 반대편
  • , 소정의 InjectionTarget 정의는, 바로 그 빈의 수명을 연장한다.

나는 두 개의 인터페이스 구현이 종종 자신의 상태 중 일부를 공유한다는 것을 알 수 있었다. 그래서 나는 독특한 클래스를 사용하여 impelment하기로 결정했습니다 다음 JndiBean를! 그 콩에서

, 방법의 대부분은 (또는 기본값) 비어 이러한 인터페이스의 메서드로합니다 (EJB 원격 인터페이스와 모든 확장 @Remote 인터페이스를 반환해야합니다
  • Bean#getTypes

    을 제외하는 수 AnnotationLiteral@JndiClient 인터페이스에 대응 : 하나의 원소를 포함하는 집합을 반환
  • Bean#getQualifiers)이 인터페이스를 통해 호출 될 수있다.
  • Contextual#create (당신은 콩의 콘텐츠를 확장하지 않았다 잊으 셨나요?) 조회 수행하는 :

    @Override 
    public T create(CreationalContext<T> arg0) { 
        // Some classloading confusion occurs here in my case, but I guess they're of no interest to you 
    
        try { 
         Hashtable contextProps = new Hashtable(); 
         contextProps.putAll(jndiProperties); 
         Context context = new InitialContext(contextProps); 
         Object serverSide = context.lookup(jndiName); 
         return interfaceClass.cast(serverSide); 
        } catch (NamingException e) { 
         // An unchecked exception to go through weld and break the world appart 
         throw new LookupFailed(e); 
        } 
    } 
    

을 그리고 그 모든

사용입니까? 이러한 문제

미래가없는

private @Inject @JndiClient MyRemoteEJB instance; 

그리고 작동으로

글쎄, 지금 내 글래스 피쉬 자바 클라이언트 코드에, 내가 쓸 수있는 일?

음, 지금은 사용자 자격 증명이 관리되지 않지만 나는 C CDI : Contexts ...를 사용하면 완전히 가능할 것이라고 생각합니다. 오! 컨텍스트 : scopes!

1

CDI 사양의 3.5 절이 도움이 될 것입니다. EJB 어노테이션의 일부 특성을 사용할 수도 있습니다. 또한 (아마도이 ​​사실을 말할 필요가 없습니다.) 서버를 참조하기 위해 JNDI가 클라이언트에 올바르게 설정되어 있는지 확인하고 필요한 인터페이스를 클라이언트 jar에 압축하십시오.