Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Andy McCright
    @andymc12

    Hi @jwcarman - hopefully you saw my response in the MP Rest Client gitter too - putting on my Open Liberty hat... I think there are a few reasons why @Path is required on the resource class:
    1) it makes it clear that it is a root resource class
    2) it is a bean-defining annotation when used with CDI
    3) it avoids complexity when multiple inheritance (i.e. multiple interfaces) is in play

    As mentioned in the other thread, you should only need to duplicate the @Path annotation (or work around it by using baseUri) - the method- and parameter-level annotations are inherited as per the spec.

    James Carman
    @jwcarman
    @andymc12 just saw this. Thanks!
    Now I'm having trouble with constructor-based injection.
    I can't inject a dependency into my root resource class via adding @Inject onto the ctor, but if I put it on the field, everything works just fine
    I would much rather use constructor-based injection, as that makes it easier to test my stuff
    and I hate setters for that type of stuff
    Andy McCright
    @andymc12

    @jwcarman that's another optional requirement in the spec:

    The following additional requirements apply when using Managed Beans, CDI-style Beans or EJBs as resource classes, providers or Application subclasses:
    ...
    Support for constructor injection of JAX-RS resources is OPTIONAL. Portable applications MUST instead use fields or bean properties in conjunction with a @PostConstruct annotated method. Im- plementations SHOULD warn users about use of non-portable constructor injection.

    I think we have a feature request work item to support constructor injection - let me see if I can find it.

    James Carman
    @jwcarman
    Andy McCright
    @andymc12
    hmm... actually, it might work today as long as you have a public no-arg constructor too: OpenLiberty/open-liberty#7010
    James Carman
    @jwcarman
    Then I can't make my fields final (unless I set them to null)
    That seemed to work, but man that's ugly
    Andy McCright
    @andymc12
    could your public no-arg constructor call one of the other constructors but pass in null? or is that what you mean by ugly?
    James Carman
    @jwcarman
    @Path("persons")
    public class PersonResource {
    
        private final PersonRepository repository;
    
        public PersonResource() {
            this(null);
        }
    
        @Inject
        public PersonResource(PersonRepository repository) {
            this.repository = repository;
        }
    
        @GET
        @Produces(MediaType.APPLICATION_JSON)
        @Path("{id}")
        public Person getPerson(@PathParam("id") String id) {
            return repository.findById(id);
        }
    }
    yeah, that's kinda ugly, wouldn't you agree?
    JAX-RS is supposed to pick the "longest" constructor, isn't it? I don't know what CDI is supposed to do here.
    Andy McCright
    @andymc12
    it's all relative. :) but the more parameters in the constructor, the uglier it gets.
    James Carman
    @jwcarman
    I'm okay with the 1 I have here :)
    So, is this just a "work around" for a bug in OL?
    or is this per the spec and how things are supposed to work?
    Oh, and now I have to test this no-arg constructor or else it jacks up my coverage numbers :(
    Andy McCright
    @andymc12
    I think it is a requirement for CDI - I'm not a CDI expert, but I think RequestScoped beans need to have a public, no-arg constructor. I wonder if you could change the scope (try @ApplicationScoped or maybe @Dependent) if it would work without the no-arg constructor
    James Carman
    @jwcarman
    @ApplicationScoped didn't work...
    but, for some reason, @Dependent does
    I really need to get better with CDI. I've been in "Spring Boot Land" for so long.
    Andy McCright
    @andymc12
    @Azquelt or @tevans78 might know more, but I think @Dependent doesn't produce a Java proxy, so it doesn't need the no-arg constructor. That might explain the requirement.
    James Carman
    @jwcarman
    Yeah, this is where things start to get really fuzzy for me with CDI.
    They seem a bit overzealous with the proxies
    I get why they're needed in certain cases, but CDI seems to have gone overboard.
    Andy McCright
    @andymc12
    yeah, as a user, I really like CDI - for the most part it simplifies code and "just works", but (like many things) there are a few "gotchas" that don't seem to make a lot of sense.
    James Carman
    @jwcarman
    I'm sure it's just growing pains for me and I'll get used to it eventually, after I bump my head against the wall enough times.
    There are gotchas in Spring too, but I have hit them so many times that I just naturally shy away from those approaches to avoid it
    James Carman
    @jwcarman
    Thanks, as usual, for the convo, @andymc12. If we ever get to have conferences again, it'd be good to meet you face-to-face and buy you a beer for how helpful you've been to me.
    Andy McCright
    @andymc12
    no problem - until then, virtual cheers! :)
    Andrew Rouse
    @Azquelt
    @andymc12 is right, if it's not @Dependent then CDI needs to be able to proxy it, so it must have a non-private no-arg constructor
    https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#unproxyable lists the requirements to allow CDI to proxy a class, and the situations when it needs to do so
    Benjamin Marwell
    @bmarwell
    @Inject public PersonResource(Bean bean) -- JAX-RS does not support constructor injection (sadly). :( @jwcarman
    Benjamin Marwell
    @bmarwell
    @jwcarman @andymc12 this one is related as well: eclipse/microprofile#50
    If I am reading this, there will be a CDI dependency in JAX-RS?
    Bjørn-Willy Arntzen
    @bwa
    Trying to find a golden solution for liberty-maven-plugin, but have issues ... OpenLiberty/ci.maven#943
    mdagit
    @mdagit
    I have a JAX-RS ContainerRequestFilter which does some checks and then if it doesn't like the smell it will do:
    requestContext.abortWith(Response.status(Status.FORBIDDEN).entity(Map.of("error", err)).build());
    but I'm getting this in OL messages.log when that code is triggered:
    [9/25/20, 14:16:47:531 PDT] 0000001e org.apache.cxf.jaxrs.utils.JAXRSUtils E No message body writer has been found for class java.util.ImmutableCollections$Map1, ContentType: /
    and the client sees a 500 http status instead of a 403 status
    not sure what to do about that -- what kind of jax-rs runtime can't serialize a Map<String,String> ?
    Andy McCright
    @andymc12

    @mdagit you may need to specify the content type in your response - something like:
    requestContext.abortWith(Response.status(Status.FORBIDDEN).entity(Entity.entity(Map.of("error", err), MediaType.APPLICATION_JSON)).build());
    or
    requestContext.abortWith(Response.status(Status.FORBIDDEN).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML).entity(Map.of("error", err)).build());

    I'm just randomly guessing at the content type you want - but ultimately, that's the issue - the runtime doesn't know what to serialize the map to.

    mdagit
    @mdagit
    @andymc12 oh good idea let me try that. For some reason i had it in my head that text/plain was a default implicit content type but maybe i just made that up.
    Andy McCright
    @andymc12
    yeah, I can't find any mention of a default MediaType - but I did find that there is a type(...) method on the ResponseBuilder class that might be cleaner than the snippets I first suggested. ex:
    requestContext.abortWith(Response.status(Status.FORBIDDEN).type("text/plain").entity(Map.of("error", err)).build());
    mdagit
    @mdagit
    @andymc12 - you were right! Things working swimmingly now. Getting a real 403 back. I don't really understand how the server determines its providers; I think what happened is my maven build used to pull in jackson, and i removed that from my war build, and now OL is using apache CXF? Is that a possible explanation of why this used to work? But I thought there is all this class loader separation and whatnot to prevent that sort of side-effect?
    Andy McCright
    @andymc12
    I'm not sure. Did you switch from jaxrs-2.0 to jaxrs-2.1? You would get different behavior in that case.
    actually, now that you mention it, I think the Jackson provider would match any object type and any content type, so removing Jackson might've broken this.
    I'm logging out. I'm glad things are working for you now. Have a good weekend!
    mdagit
    @mdagit
    @andymc12 thanks again!