interface - Java – custom annotation won't be considered -
i have built employeeendpoint holds different methods create, update, remove, , many more. simplify question used create method.
because want scalable application i’ve built interface holds base methods. within interface can annotate methods jax-rs-annotations. because inherited have override interface method within employeeendpoint.
interface
public interface restcollection<t> { @post @consumes(mediatype.application_json) @produces(mediatype.application_json) public t create(t entity) throws exception; } endpoint
@stateless @path(“employee“) public class employeeendpoint implements restcollection<employee> { @override public employee create(employee employee) throws exception { return this.createemployee(employee); } } the example above works fine. if want add custom annotation can do:
solution 1
public interface restcollection<t> { @post @consumes(mediatype.application_json) @produces(mediatype.application_json) @permissions(role.admin) public t create(t entity) throws exception; } or
solution 2
@stateless @path(“employee“) public class employeeendpoint implements restcollection<employee> { @override @post @consumes(mediatype.application_json) @produces(mediatype.application_json) @permissions(role.admin) public employee create(employee employee) throws exception { return this.createemployee(employee); } } but solution 1 isn’t idea, because not every entity can created administrator. , solution 2 loosing advantage of scalability , less code annotations. best way be:
solution 3
@stateless @path(“employee“) public class employeeendpoint implements restcollection<employee> { @override @permissions(role.admin) public employee create(employee employee) throws exception { return this.createemployee(employee); } } but when catch permissions-annotation within jax-rs' containerrequestfilter interface method called filter value of null don’t understand.
@context private resourceinfo resourceinfo; resourceinfo.getresourcemethod().getannotation(permissions.class) // null annotation
@namebinding @retention(retentionpolicy.runtime) @target({elementtype.method, elementtype.type}) public @interface permissions { role[] value() default {}; } enum
public enum role { admin, user } is possible in way go solution 3 or different approach have same advantage?
update
because reason doesn't seem code posted show authorizationfilter. therefore used this post.
authorizationfilter
@provider @priority(priorities.authorization) public class authorizationfilter implements containerrequestfilter { @inject @authenticateduser private user authenticateduser; @context private resourceinfo resourceinfo; @override public void filter(containerrequestcontext requestcontext) throws ioexception { class<?> resourceclass = resourceinfo.getresourceclass(); list<role> classroles = extractroles(resourceclass); method resourcemethod = resourceinfo.getresourcemethod(); list<role> methodroles = extractroles(resourcemethod); try { if (methodroles.isempty()) checkpermissions(classroles, requestcontext.getheaderstring(httpheaders.authorization)); else checkpermissions(methodroles, requestcontext.getheaderstring(httpheaders.authorization)); } catch (notauthorizedexception e) { requestcontext.abortwith( response.status(response.status.unauthorized).build()); } catch (exception e) { requestcontext.abortwith( response.status(response.status.forbidden).build()); } } private list<role> extractroles(annotatedelement annotatedelement) { if (annotatedelement == null) return new arraylist<role>(); else { permissions perms = annotatedelement.getannotation(permissions.class); if (perms == null) return new arraylist<role>(); else { role[] allowedroles = perms.value(); return arrays.aslist(allowedroles); } } } private void checkpermissions(list<role> allowedroles, string authorizationheader) throws notauthorizedexception, exception { if (!allowedroles.isempty()) { if (authorizationheader == null || !authorizationheader.startswith("bearer ")) throw new notauthorizedexception("authorization header must provided"); else if (!allowedroles.contains(this.authenticateduser.getrole())) throw new exception("user has no permissions"); } } }
your code looks good.
i have run few tests , reason can think of using 2 different permission types on employee resource 1 on filter. (check imports)
not sure filter code, mine working (see imports):
package com.app.filters; // todo change yours import java.io.ioexception; import java.util.arrays; import javax.ws.rs.container.containerrequestcontext; import javax.ws.rs.container.containerrequestfilter; import javax.ws.rs.container.resourceinfo; import javax.ws.rs.core.context; import com.app.services.permissions; // todo change yours public class authorizationfilter implements containerrequestfilter { @context resourceinfo resourceinfo; @override public void filter (containerrequestcontext requestcontext) throws ioexception { permissions perms = resourceinfo.getresourcemethod ().getannotation (permissions.class); system.out.println (getclass ().getsimplename () + " --> permissions: " + arrays.tostring (perms.value ())); // prints [admin] } } bonus, if want test actual value of annotation on employee resource:
.... import com.app.services.permissions; // todo change yours (the 1 on filter being same one) .... @permissions (role.admin) @override public employee create (employee employee) throws exception { class<?> [] carg = new class [1]; carg [0] = employee.class; method method = getclass ().getmethod ("create", carg); permissions perms = method.getannotation (permissions.class); system.out.println (employeeservice.class.getsimplename () + " --> permissions: " + arrays.tostring (perms.value ())); return null; }
Comments
Post a Comment