RESTEASY003130: Class is not a root resource的問題原因

wtopps發表於2017-08-08

問題描述

今天在使用dubbox的時候,在啟動服務的時候報出一個錯誤,導致應用無法啟動,錯誤的提示資訊為:
Initialization of bean failed; nested exception is java.lang.RuntimeException: RESTEASY003130: Class is not a root resource. It, or one of its interfaces must be annotated with @Path

dubbox是在dubbo的基礎上進行了restFul的擴充套件,使用了JAX-RS的擴充套件,因此可以支援restFul的呼叫,預設的呼叫方式應該為:

Interface:

@Path("interface/doSomething")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface TestService {

    @POST
    @Path("run")
    boolean test(TestDTO dto);
}

Interface Implements:

@Service
public class TestServiceImpl implements TestService {

    @Override
    public boolean test(TestDTO dto) {
        //doSomething.......
    }
}

由於dubbox是基於dubbo實現的,當我們有某些方法不想再提供restFul的介面時,只是提供dubbo的呼叫,該怎麼做呢?

於是我想當然的這麼做了:


public interface TestService {

    boolean test(TestDTO dto);
}

我把interface中的JAX-RS的註解去除了,這樣就只是提供dubbo的呼叫方式,而不提供restFul的呼叫了,然後當我啟動專案的時候,就報了上面的錯誤……

問題原因

找了好多資料,找到了原因所在,因為dubbox支援JAX-RS,因此加入相應的Jar檔案,其中就有resteasy,在其中的一個類ResourceMethodRegistry.java 中的addResourceFactory()方法,找到了問題原因:

/**
    * ResourceFactory.getScannableClass() defines what class should be scanned
    * for JAX-RS annotations.    The class and any implemented interfaces are scanned for annotations.
    *
    * @param ref
    * @param base base URI path for any resources provided by the factory, in addition to rootPath
    */
   public void addResourceFactory(ResourceFactory ref, String base)
   {
      Class<?> clazz = ref.getScannableClass();
      Class restful = GetRestful.getRootResourceClass(clazz);
      if (restful == null)
      {
         String msg = Messages.MESSAGES.classIsNotRootResource(clazz.getName());
         for (Class intf : clazz.getInterfaces())
         {
            msg += " " + intf.getName();
         }
         throw new RuntimeException(msg);
      }
      addResourceFactory(ref, base, restful);
   }

可以看到ResourceFactory.getScannableClass()定義了掃描哪些class檔案,進入看一下具體的實現:

public class DubboResourceFactory implements ResourceFactory {

    private Object resourceInstance;
    private Class scannableClass;

    public DubboResourceFactory(Object resourceInstance, Class scannableClass) {
        this.resourceInstance = resourceInstance;
        this.scannableClass = scannableClass;
    }

    public Class<?> getScannableClass() {
        return scannableClass;
    }
}    

這裡只給出部分原始碼,從此可以看出scannableClass是由dubbo註解的class,因此可以明白其報錯的原因,JAX-RS會掃描被dubbo註解的class實現的interface,由於interface沒有註解@Path,因此丟擲了異常。

總結

使用dubbox後,提供dubbo服務的類必須註解@Path,即使該類中沒有提供restFul的呼叫,否則會報出”Class is not a root resource”的異常,那我們有的類中的確沒有方法需要提供restFul呼叫的時候該怎麼辦呢?可以在方法上不加任何註解,這樣做的話只可以進行dubbo方式的呼叫

@Path("interface/doSomething")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface TestService {

    boolean test(TestDTO dto);
}

相關文章