Forums Register Login

how to create custom annotation in jersey

+Pie Number of slices to send: Send
want to create a custom annotation to check the user role and username (similar to@RolesAllowed)

tried google it , but no luck.

got some hint from here:
an example on how to create seculity filter

author said I can create a filter similar to "SecurityContextFilter" as he explained. I don't know how to read the injected values in my custom annotation.
For example, for @MyAnnotation("username", "rolename"), How can I get the value of "username" and "rolename" in "MySecurityContextFilter".

Anyone can show me an example? Hope I explained my question clear enough. thanks a lot!
+Pie Number of slices to send: Send
So you want to restrict things to hard-coded usernames in the code? Does that really make any sense?
+Pie Number of slices to send: Send
Actually its for authorization. for a request uri: webservice/XXX/{userID}. it should only be accessed by administrator or user(other roles: user, superuser, etc) itself.

So, basically this filter will check the userID and {userID} in URI if they are match and the roles (user or superuser).

please check this post also
similar question

thanks!
+Pie Number of slices to send: Send
 

Yu Chen wrote:
Actually its for authorization. for a request uri: webservice/XXX/{userID}. it should only be accessed by administrator or user(other roles: user, superuser, etc) itself.


That still does not explain why you want to hard-code usernames in an annotation.
+Pie Number of slices to send: Send
No, I'm not going to hard-code it. the userid will be retrieved from principal through securitycontext.

Actually I borrowed it from the webpage linked in previous post.

"
You can inject the UriInfo to obtain the "username" path parameter.
Your annotation could declare the path parameter name that needs to be
checked, e.g.

@MyRolesChecker("username", "myole");
public String get() { ... }
"

For me, probably @MyAnnotation("rolename") will be enough. the userIDs will be retrieved from pricipal and URI.


thanks!
+Pie Number of slices to send: Send
+Pie Number of slices to send: Send
Thanks Ulf! That's a good tutorial. Sorry for the late response, I was out of internet for a while.

I still have trouble to get the annotation values.

As in the sample code:
"
AnnotationTest at = new AnnotationTest();
Class atClass = at.getClass();

Method mth = atClass.getMethod("someMethod");
annotations = mth.getAnnotations();
"

How can I implement it in my Jersey request/resource filter? the filter don't know which class will apply this annotation.

Thanks a lot!
+Pie Number of slices to send: Send
The article actually shows how to do that with the Audit annotation - the AuditFilter is only applied to resource methods that have that annotation.
+Pie Number of slices to send: Send
Thanks Ulf!

Actually I don't know how to create the AuditFilter to read the "Audit" annotation values. I tried to figure it out from the tutorial, but still no clue.
+Pie Number of slices to send: Send
It's in the ResourceFilterFactory class, almost at the end - to every AbstractMethod (an object that goes with a resource method, from what I understand) it adds an AuditFilter if the method is annotated with "@Audit".
+Pie Number of slices to send: Send
Thanks for your prompt response.

The ResourceFilterFactory just adds all the filters needed to apply. My problem now is how to implement the AuditFilter.

E.g. in the tutorial,
@Audit("edit-book")

How to get the value "edit-book" in AuditFilter.
+Pie Number of slices to send: Send
The AnnotationsExample I linked to earlier shows that - both FirstAnno and SecondAnno have parameters which that are later retrieved at runtime.
+Pie Number of slices to send: Send
I saw it. However, it requires a main class to access it. As below: "AnnotationTest at"

For the REST service, you don't know which class will be added annotation. So in my Filter class, how to do something like in the sample code:

"
AnnotationTest at = new AnnotationTest();
Class atClass = at.getClass();
"

The filter class don't know what class is "AnnotationTest".

Thanks a lot!
+Pie Number of slices to send: Send
I don't understand where you see the difficulty.

If you want a filter to so something about a particular annotation X it's annotated with, or one of its methods or fields are annotated with, then it would do it exactly as that example shows. No main method is required, that can happen in any method, or the constructor. The "AnnotationTest" of the example would be the filter object and class itself.

If you want some external class (not a resource) to do something about a resource class being annotated, then the approach of a ResourceFilterFactory would work - it gets called for each resource filter, no matter what class it is. Obviously it needs to know which annotations to look out for, but that's a reasonable requirement - otherwise there's no way it could do whatever needs doing for each annotation.
+Pie Number of slices to send: Send
I think I want to go with the first method.
Looks like working now, but not sure if it is the right way:

  • 1. I have to add the annotation value in ResourceFilterFactory through the AbstractMethod
  • 2. Initialize the annotation values in filter constructor








  • The previous problem I was missing is that I didn't pass by annotation values to filter as in <1> and <2>:

    securityFilters.add(new UserInRoleSecurityContextFilter(userInRoleAllowed.value()));

    this.rolesAllowed = (rolesAllowed != null) ? rolesAllowed : new String[] {};


    So, my understand is that each method has @UserInRoleAllowed annotation will have its own/separate UserInRoleSecurityContextFilter?


    ======================

    other questions:

    1. why am.getResource().getAnnotation() not working.

    this example in post uses both statements.

    UserInRoleAllowed userInRoleAllowed = am.getResource().getAnnotation(UserInRoleAllowed.class); //fails
    UserInRoleAllowed userInRoleAllowed = am.getAnnotation(UserInRoleAllowed.class); //works

    2. in <3>
    if (securityContext == null) {
    // securityContext should be set up in constructor, but still null <3>
    securityContext = request.getSecurityContext();
    }

    securityContext is declared as "private @Context", it suppose to be set up/initialized by jersey after constructor method. Why it is still null and I have to call request.getSecurityContext();

    If you can give me some explanation, I really appreciate.




    +Pie Number of slices to send: Send
     

    each method has @UserInRoleAllowed annotation will have its own/separate UserInRoleSecurityContextFilter?


    It needs to, the way this code works, since the list of allowed roles is encapsulated in the filter. Since each method can have a different set of roles, you need a different filter.

    why am.getResource().getAnnotation() not working.


    I'm sure it works fine, it just doesn't do what you think it does. Read the comments that go with the two different usages in the example you linked to - they explain the difference.
    +Pie Number of slices to send: Send
    A million thanks!!!
    There are 10 kinds of people in this world. Those that understand binary get this tiny ad:
    a bit of art, as a gift, the permaculture playing cards
    https://gardener-gift.com


    reply
    reply
    This thread has been viewed 6925 times.
    Similar Threads
    Developing rich annotations
    is @WebServiceProvider only for JavaSE
    servlet annotation
    @SqlResultSetMapping
    How to set the content type for a GET request from a browser
    More...

    All times above are in ranch (not your local) time.
    The current ranch time is
    Mar 29, 2024 08:10:52.