Jax-rs, JavaEE7, Java8: не было объекта, доступного для внедрения в SystemInjecteeImpl

Я инженер-программист в компании-разработчике программного обеспечения среднего размера и некоторое время работаю над фреймворком для отдыха. Это классные вещи о методах по умолчанию в интерфейсах Java8. Поэтому я решил использовать это поведение по умолчанию для реализации функций CRUD, каждый из которых разделен собственным интерфейсом (ICreateResource). Логика, которая выполняется в методах CRUD, обеспечивается дополнительным классом, который также объявлен как интерфейс IResourceStateControl.

Так вот в чем проблема. При внедрении RatingResourceStateControl, который реализует IResourceStateControl, в RatingResourceStateBean, который реализует ICreateResource, возникает исключение «Нет объекта, доступного для внедрения в SystemInjecteeImpl" возникает при выполнении запроса.

public interface ICreateResource
{
    IResourceStateControl getResourceStateControl();

    @POST
    @Consumes(APPLICATION_JSON)
    @Produces(COLLECTION_JSON)
    default Response post(@Context UriInfo uriInfo, ApplicationState representation)
    {
        try
        {
            Collection collection = getResourceStateControl().post(uriInfo, representation);
            return Response.created(collection.getHref().get()).entity(collection).build();
        }
        catch (Exception exception)
        {
            throw new WebApplicationException(exception.getMessage(), exception, Response.Status.INTERNAL_SERVER_ERROR);
        }
    }
}

@Dependent
public class RatingResourceStateControl implements IResourceStateControl
{

    @Override
    public Collection get(UriInfo uriInfo, int start, int size, long parentResourceId)
    {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Collection get(UriInfo uriInfo, long id)
    {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Collection post(UriInfo uriInfo, ApplicationState representation)
    {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Boolean delete(long id)
    {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Collection put(UriInfo uriInfo, long id, ApplicationState representation)
    {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Collection patch(UriInfo uriInfo, long id, ApplicationState representation)
    {
        // TODO Auto-generated method stub
        return null;
    }
}
@Stateless
@Path("/" + RATINGS_PATH)
public class RatingResourceStateBean implements ICreateResource
{
    @Inject
    private RatingResourceStateControl ratingResourceControl;

    @Override
    public IResourceStateControl getResourceStateControl()
    {
        return ratingResourceControl;
    }
}

Но все работает при использовании абстрактного класса для обеспечения функциональности.

public abstract class AbstractResourceState
{
    protected abstract IResourceStateControl getResourceStateControl();

    @Context
    private UriInfo uriInfo;
    @Context
    private HttpServletRequest httpServletRequest;

    @POST
    @Consumes(APPLICATION_JSON)
    @Produces(COLLECTION_JSON)
    public Response post(ApplicationState representation)
    {
        try
        {
            Collection collection = getResourceStateControl().post(uriInfo, representation);
            return Response.created(collection.getHref().get()).entity(collection).build();
        }
        catch (Exception exception)
        {
            throw new WebApplicationException(exception.getMessage(), exception, Response.Status.INTERNAL_SERVER_ERROR);
        }
    }
}

@Stateless
@Path("/" + RATINGS_PATH)
public class RatingResourceStateBean extends AbstractResourceState
{
    @Inject
    private RatingResourceStateControl ratingResourceControl;

    @Override
    protected IResourceStateControl getResourceStateControl()
    {
        return ratingResourceControl;
    }
}

API работает с подходом абстрактного класса, но было бы очень неплохо контролировать, какой метод CRUD доступен, просто реализовав соответствующий интерфейс. Все развернуто на сервере приложений payara 4.1.1.

С наилучшими пожеланиями Руди Полезно Бесполезно


person rudi    schedule 08.02.2017    source источник


Ответы (1)


Вы пытаетесь внедрить ресурс JAX-RS @Context UriInfo uriInfo в ICreateResource.post, что является методом по умолчанию. Так как JAX-RS API основан на Java 7, вам нужно быть осторожным при использовании методов по умолчанию, потому что спецификация ничего не говорит о них. Все зависит от того, как API отражения предоставляет информацию о методах по умолчанию.

Проблема также может заключаться в том, что вы переопределяете метод по умолчанию, но не копируете аннотацию @Context. Когда сервер сканирует класс, он не увидит никакой аннотации @Context в сигнатуре метода (как если бы метод по умолчанию не существовал).

person OndroMih    schedule 09.02.2017
comment
Да это ответ. При доступе к члену @context через метод получения интерфейса он работает с GET, но не с POST. Но это другая проблема, может быть. - person rudi; 15.02.2017