I'm a software engineer at a medium sized software company and working on a rest framework for quiet a while. Their is that cool stuff about the default methods in Java8 interfaces. So I decided to use this default behavior to implement the CRUD functionality, each separated in it's own interface (ICreateResource). The logic which is executed in the CRUD methods is provided by an extra class which is also declared as an interface IResourceStateControl.
So here is the problem. When injecting RatingResourceStateControl which implements IResourceStateControl into RatingResourceStateBean which implements ICreateResource the exception "There was no object available for injection at SystemInjecteeImpl" is raised when doing a request.
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;
}
}
But everything works when using an abstract class for providing the functionality.
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;
}
}
The api is working with the abstract class approach, but it would be very nice to have the control what CRUD method is available by simply implement the appropriate interface. Everything is deployed on a payara 4.1.1 app server.
Best Regards Rudi
You are trying to inject a JAX-RS resourse @Context UriInfo uriInfo
into ICreateResource.post
, which is a default method. Since JAX-RS API is based on Java 7, you need to be careful how you use default methods, because the specification doesn't say anything about them. It all depends on how the reflection API exposes the information about default methods.
The problem may also be that you are overriding the default method, but you didn't copy the @Context
annotation. When the server scans the class, it will not see any @Context
annotation in the method signature (as if the default method didn't exist).