2012-06-26 2 views
0

Map<String, Object>을 매개 변수로 사용하는 MBean에 문제가 있습니다. 내가 프록시 개체를 사용하여 JMX를 통해 그것을 실행하려고하면, 나는 예외를 얻을 :JMX 작업이 인터페이스를 매개 변수로 사용할 수 있습니까?

Caused by: javax.management.ReflectionException 
    at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:231) 
    at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:668) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
Caused by: java.lang.IllegalArgumentException: Unable to find operation updateProperties(java.util.HashMap) 

인터페이스가 아닌 실제 구현 클래스를 사용하려고 시도하고 이것이인지 확인하지 않는 것 같습니다 필요한 인터페이스의 자식. 확장 클래스에서도 마찬가지입니다 (예 : HashMap 선언, LinkedHashMap 전달). 그러한 메소드에 인터페이스를 사용하는 것이 불가능하다는 것을 의미합니까? 지금은 HashMap을 받아들이 기 위해 메서드 서명을 변경하여 그 주위를 돌아 다니고 있지만, MBeans에서 인터페이스 (또는 확장 클래스)를 사용할 수 없다는 것이 이상하게 보입니다.

편집 : 프록시 개체는 JmxInvocationHandler이라는 사내 유틸리티 클래스에 의해 생성됩니다. (잘하면) 관련 부분은 다음과 같습니다 :

public class JmxInvocationHandler implements InvocationHandler 
{ 
    ... 
    public static <T> T createMBean(final Class<T> iface, SFSTestProperties properties, String mbean, int shHostID) 
    { 
     T newProxyInstance = (T) Proxy.newProxyInstance(iface.getClassLoader(), new Class[] { iface }, (InvocationHandler) new JmxInvocationHandler(properties, mbean, shHostID)); 
     return newProxyInstance; 
    } 
    ... 
    private JmxInvocationHandler(SFSTestProperties properties, String mbean, int shHostID) 
    { 
     this.mbeanName = mbean + MBEAN_SUFFIX + shHostID; 
     msConfig = new MsConfiguration(properties.getHost(0), properties.getMSAdminPort(), properties.getMSUser(), properties.getMSPassword()); 
    } 
    ... 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
    { 
     if (management == null) 
     { 
      management = ManagementClientStore.getInstance().getManagementClient(msConfig.getHost(), 
        msConfig.getAdminPort(), msConfig.getUser(), msConfig.getPassword(), false); 
     } 

     final Object result = management.methodCall(mbeanName, method.getName(), args == null? new Object[] {} : args); 
     return result; 
    } 
} 
+0

Hi Thor; 프록시 객체를 생성하는 코드를 제공 할 수 있습니까? – Nicholas

+0

저는 사내 유틸리티 클래스를 사용하고 있습니다. 솔직히 말해서 실제로 진행되고있는 일을 실제로 해결할 수 있을지 확신하지 못합니다. 보안과 관련하여 많은 추가 작업을하고 있으며, 지금까지 본 적이 있지만) 중요한 비트를 추출하여 게시물에 추가하려고 노력할 것입니다. – Thor84no

답변

2

작성했습니다. MBean에의 조작 서명 (A 무정하는 때문에

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
    { 
     if (management == null) 
     { 
      management = ManagementClientStore.getInstance().getManagementClient(msConfig.getHost(), 
        msConfig.getAdminPort(), msConfig.getUser(), msConfig.getPassword(), false); 
     } 

     final Object result = management.methodCall(mbeanName, method.getName(), args == null? new Object[] {} : args); 
     return result; 
    } 

: JMX 호출 가끔 .... 최고의 구성 유틸리티 클래스의 대포 사료를 만들기 :

이 사람을, 나는 의심 문제가 유래에 관한 부엉이)는 전달 된 인수의 클래스에서 결정됩니다. getClass()java.util.Map을 반환 할 실제 구체적인 객체를 전달할 수 없으므로 직접적인 유형의 인수 자체를 사용하여 절대 일치하지 않습니다. 유사한 문제는 같은 이유로 프리미티브에서 발생합니다.

은 좀 더 자세히이 문제 (또는 문제가 당신이 가지고있는 생각을) 설명으로이 blog post이, "MetaMBean을 만드는 까다로운 부분 하나"와 단락 개방으로 시작 참조하지만, MBeanServer [연결]의 invoke 방법은 다음과 같습니다

invoke(ObjectName name, String operationName, Object[] params, String[] signature) 

처음이 개 마지막 인수가 정확히 서버에 게시 된 모든 작전이 호출되어야 사이에 어떤 동작을 지정한다는 점에서 탐색합니다. 이 문제를 피할 수있는 가장 좋은 방법은 서명을 "추측"하지 않고 대상 이름의 MBeanInfoMBeanOperationInfo을 질문하고 (가능하면 캐싱하여) 수행 할 수있는 ObjectName과 작업 이름에만 의존하는 것입니다. . 추측 할 필요가 없도록 MBeanOperationInfos에서 서명을 제공합니다.

  1. 가 MBean의 조작 이름 (즉, 더 오버로드가 없습니다) 다음 방금 검색 연산 이름을 사용할 수 있습니다 고유 경우

    이 실제로 문제의 경우, 당신은 그것을 해결할 수있는 몇 가지 방법입니다 MBeanInfo.

  2. MBean의 연산이 오버로드 된 경우 (즉, 동일한 이름이지만 매개 변수가 다른 여러 연산이있는 경우) 모두 매개 변수 수가 다르면 일치하는 모든 op 이름을 반복하여 올바른 서명을 쉽게 확인할 수 있습니다. MBeanOperationInfo 및 param 카운트에 의한 매칭
  3. # 1과 # 2가 적용되지 않는 경우 ... 까다로운 문제이며 MBean 코드의 메서드 서명을 다시 평가할 것입니다.
  4. # 1과 # 2가 적용되지 않고 # 3이 준수하지 않는 경우 MetaMBean이라고하는 Gmx에서이 클래스를 살펴보십시오. 최신 개정판에서는 Groovy를 사용하여 MBean의 MBeanInfo를 사용하여 컴파일 된 런타임 인터페이스를 생성하여 메소드 호출에서 상속 (및 autoboxing)이 가능하도록했습니다. JavaScript (자바 6+에 ​​내장 된 미덕을 가짐) 또는 다른 여러 JVM 스크립팅 언어에서도 동일한 방법을 구현할 수 있습니다. (I 어쨌든 ...... 그루비 작업 이후 실제로 꽤 잘 작동했지만) 또는

난이 도움이 희망 알려진 작업 서명에 대해 패턴 일치를 시도한 previous version 봐. 이것이 근본 원인이 아니라는 것을 알게되면, 나는 아무 것도 말하지 않았다는 것을 잊어 버리십시오 ....

+0

매우 흥미롭고 잘 생각한 대답. 감사. 이 수업은 다른 프로젝트에 있고 내가 우선적 인 문제를 다루었 기 때문에 지금 당장 시험 사용해보기가 어렵습니다. 지금 당장은 올바른 답변 일 가능성이 높으므로 귀하의 답변에 대해 찬성표를 드리겠습니다. 일단 기회가 있으면이 방법으로 해결할 수 있는지 여부를 알려 드리겠습니다. 고마워. – Thor84no

관련 문제