Я пытаюсь свести к минимуму повторяющийся код для нескольких обработчиков ресурсов JAX-RS, все из которых требуют нескольких одинаковых параметров пути и запроса. Основной шаблон URL для каждого ресурса выглядит следующим образом:
/{id}/resourceName
и каждый ресурс имеет несколько подресурсов:
/{id}/resourceName/subresourceName
Итак, пути ресурсов/подресурсов (включая параметры запроса) могут выглядеть как
/12345/foo/bar?xyz=0
/12345/foo/baz?xyz=0
/12345/quux/abc?xyz=0
/12345/quux/def?xyz=0
Общими частями ресурсов foo и quux являются @PathParam("id") и @QueryParam("xyz"). Я мог бы реализовать классы ресурсов следующим образом:
// FooService.java
@Path("/{id}/foo")
public class FooService
{
    @PathParam("id") String id;
    @QueryParam("xyz") String xyz;
    @GET @Path("bar")
    public Response getBar() { /* snip */ }
    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}
// QuuxService.java
@Path("/{id}/quux")
public class QuxxService
{
    @PathParam("id") String id;
    @QueryParam("xyz") String xyz;
    @GET @Path("abc")
    public Response getAbc() { /* snip */ }
    @GET @Path("def")
    public Response getDef() { /* snip */ }
}
Мне удалось избежать повторения ввода параметров в каждый метод get*.  1 Это хороший старт, но я бы хотел, чтобы избежать повторения в классах ресурсов также. Подход, который работает с CDI (который мне также нужен), заключается в использовании базового класса abstract, который FooService и QuuxService мог бы extend:
// BaseService.java
public abstract class BaseService
{
    // JAX-RS injected fields
    @PathParam("id") protected String id;
    @QueryParam("xyz") protected String xyz;
    // CDI injected fields
    @Inject protected SomeUtility util;
}
// FooService.java
@Path("/{id}/foo")
public class FooService extends BaseService
{
    @GET @Path("bar")
    public Response getBar() { /* snip */ }
    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}
// QuuxService.java
@Path("/{id}/quux")
public class QuxxService extends BaseService
{   
    @GET @Path("abc")
    public Response getAbc() { /* snip */ }
    @GET @Path("def")
    public Response getDef() { /* snip */ }
}
Внутри методов get* инъекция CDI (чудом) работает правильно: поле util не равно null. К сожалению, инъекция JAX-RS не работает; id и xyz являются null в методах get* FooService и QuuxService.
Есть ли исправление или обходной путь для этой проблемы?
Учитывая, что CDI работает так, как мне бы хотелось, мне интересно, является ли ошибка при вводе @PathParam (и т.д.) в подклассы ошибкой или просто частью спецификации JAX-RS.
Другой подход, который я уже пробовал, использует BaseService как одну точку ввода, которая делегирует FooService и QuuxService по мере необходимости. Это в основном, как описано в RESTful Java с JAX-RS с использованием локаторов подресурсов.
// BaseService.java
@Path("{id}")
public class BaseService
{
    @PathParam("id") protected String id;
    @QueryParam("xyz") protected String xyz;
    @Inject protected SomeUtility util;
    public BaseService () {} // default ctor for JAX-RS
    // ctor for manual "injection"
    public BaseService(String id, String xyz, SomeUtility util)
    {
        this.id = id;
        this.xyz = xyz;
        this.util = util;
    }
    @Path("foo")
    public FooService foo()
    {
        return new FooService(id, xyz, util); // manual DI is ugly
    }
    @Path("quux")
    public QuuxService quux()
    {
        return new QuuxService(id, xyz, util); // yep, still ugly
    }
}
// FooService.java
public class FooService extends BaseService
{
    public FooService(String id, String xyz, SomeUtility util)
    {
        super(id, xyz, util); // the manual DI ugliness continues
    }
    @GET @Path("bar")
    public Response getBar() { /* snip */ }
    @GET @Path("baz")
    public Response getBaz() { /* snip */ }
}
// QuuxService.java
public class QuuzService extends BaseService
{
    public FooService(String id, String xyz, SomeUtility util)
    {
        super(id, xyz, util); // the manual DI ugliness continues
    }
    @GET @Path("abc")
    public Response getAbc() { /* snip */ }
    @GET @Path("def")
    public Response getDef() { /* snip */ }
}
Недостатком этого подхода является то, что ни инъекция CDI, ни инъекция JAX-RS не работают в классах субресурсов. Причина этого довольно очевидна:  2 но это означает, что я должен вручную повторно вводить поля в конструктор подкласса, который является грязным, уродливым и не позволяет мне легко настроить дальнейшую инъекцию. Пример: скажем, я хотел @Inject экземпляр в FooService, но не QuuxService. Поскольку я явно создаю подклассы BaseService, инъекция CDI не будет работать, поэтому уродство продолжается.
tl; dr Какой правильный способ избежать повторного ввода полей в классы обработчиков ресурсов JAX-RS?
И почему не наследуемые поля, введенные JAX-RS, в то время как у CDI нет проблем с этим?
Изменить 1
С небольшим направлением от @Tarlog, я думаю, что нашел ответ на один из моих вопросов,
Почему не наследуемые поля, введенные JAX-RS?
В JSR-311 §3.6:
Если в подклассе или методе реализации есть какие-либо аннотации JAX-RS, то все аннотации метода суперкласса или интерфейса игнорируются.
Я уверен, что есть настоящая причина для этого решения, но, к сожалению, этот факт работает против меня в этом конкретном случае использования. Меня все еще интересуют любые возможные обходные пути.
  1 Предостережение с использованием инъекции на уровне поля заключается в том, что теперь я привязан к экземпляру класса ресурсов для каждого запроса, но я могу жить с этим.
 2 Потому что я один вызываю new FooService(), а не контейнер/реализацию JAX-RS.