Will JAX-RS support validation groups? - jax-rs

From JSR-339:
For simplicity, JAX-RS implementations are NOT REQUIRED to support processing groups other than Default.
This severely limits usefulness of validation in JAX-RS because for example for create and update you are usually using the same model object, but for create the ID of the object should not be provided and for update the ID should be provided, which could be easily validated using validation groups. In general all model objects that are used in more than one flow are impossible to validate.
I do not understand the simplicity argument because Bean Validation already supports groups, so the JAX-RS implementation just needs to pass a group to Bean Validation implementation like Hibernate Validator.
So are there any plans to add validation groups to JAX-RS?

It turns out that it does support validation groups. From the same JSR-339:
The presence of #Valid will trigger validation of all the constraint annotations decorating a Java bean class. This validation will take place in the Default processing group unless the #ConvertGroup annotation is present.
For example this is how to validate Account bean in my custom Create or Update groups rather than the Default group:
#POST
#Consumes(MediaType.APPLICATION_JSON)
Response createAccount(#Valid #ConvertGroup(from = Default.class, to = Create.class)
Account account)
#POST
#Consumes(MediaType.APPLICATION_JSON)
Response updateAccount(#Valid #ConvertGroup(from = Default.class, to = Update.class)
Account account)
public class Account {
#Null(groups = Create.class)
#NotNull(groups = Update.class)
private String Id;
}
public interface Create {}
public interface Update {}

Related

#Auth Injection in ContainerFilter

I'm using DW 0.9.1 and it would be cool, if I could inject the #Auth XYzObject into some ContainerRequest or even better in a ContainerResponseFilter (or servlet filter).
Does anyone knows if this is possible?
The usecase: Some users does have different allowd access rates (rate limiting), e.g. max. 2 request per second and max 60 per Minute. This can be verified with the injected #Auth XYzObject.
In the end I can do this also in the Ressource, where this information is available, but as I said it would be cool to do this outside of my ressources in a filter or something else. And I do not want to do this is the authenticating/ authorization process, because rate limiting is not related to this. At the moment,all the variants I tried, nothing works, so it seems not possible, but I hope someone knows the trick.
How the #Auth annotation works is that it is handled by a ValueFactoryProvider, which is used only for (resource) method parameter injection. So you can't inject it into arbitrary locations.
However, when you created XyzObject you made it implement java.security.Principal. The reason DW makes you use this type, is because after it authenticates, it sets the Principal in the SecurityContext, as seen in the AuthFilter.
If you look at the implementation for AuthValueFactoryProvider, you will see that the way it obtains the Principal is by getting it from the SecurityContext. And that's how the Principal is injected with #Auth as a method argument.
In a ContainerRequestFilter (and in may other locations), you have access to the SecurityContext. In a filter you can get it with requestContext.getSecurityContext(). So in your filter you can get the Principal from the SecurityContext and just cast it
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
Principal principal = requestContext.getSecurityContext().getUserPrincipal();
if (principal != null) {
XyzObject xyz = (XyzObject)principal;
}
}

WCF Data Service authorization policies

I'm using the WCF Data Service and i need to implement authorization policies.
The polices are dynamic and are stored into a table that contains the target table,
the field and the allowed value.
In order to achieve this, I override the OnStartProcessingRequest method
of the DataService but I try to change the RequestUri I run into "Unauthorization" problem.
There is a way to change the RequestUri parameter in OnStartProcessingRequest method?
this code generate the exeption
protected override void OnStartProcessingRequest(ProcessRequestArgs args) {
Uri uri = new Uri(args.RequestUri + "?$filter=Id eq 3");
args.RequestUri = uri;
}
I can't use the Interceptor because the system is dynamic and entites are unknown.
Currently the adopted solution is to apply filters in client application (html5/js)
and verify the filtering parameters on server (into the OnStartProcessingRequest).
I wonder if there is a way for me to add filter parameters in OnStartProcessingRequest
or any way that can fix this problem.

Access caller roles in SLSB using Jboss7

I'm using jboss as 7.1.1.Final and have configured a security-domain using LdapExtLoginModule. The login works so far.
I now want to access the roles loaded by the module in an SLSB. I know how to access the username. My example uses ejb 3.1 and prints the username to System.out.
I don't know how to access the roles and didn't find anything in the documentation. The EJBContext provides the method isCallerInRole(String) which proves that the context itself knows the roles but I can not find a method which returns a set of roles.
I know that I could write a custom LoginModule which extends the LdapExtLoginModule and sets a custom principal containing the roles. But maybe there is an easier approach using existing functionality. Does anybody know such approach?
SLSB code:
#Stateless
#Remote(IAService.class)
public class AService implements IAService
{
#Resource
private EJBContext context;
#Override
public void printUserData() {
System.out.println("Name: " + context.getCallerPrincipal().getName());
// TODO print roles
}
}
Nobody answered my question so far and because I finally have a working solution I will now share it with you:
The Java EE API does not provide any methods to access the information in server independent way. So I tried the method of writing a login module which sets a custom principal. As it turns out this does not work either.
Inspired by the answer to this question I now use the following code to get the caller roles:
private Group getRoles() {
final Subject subject = (Subject)PolicyContext.getContext("javax.security.auth.Subject.container");
final Set<Group> groups = subject.getPrincipals(Group.class);
for (final Group group : groups) {
if ("Roles".equals(group.getName())) {
return group;
}
}
throw new IllegalStateException("No roles group found");
}
The Group returned by this method contains Principals which have the names of the users groups. This only works on JBoss whose LoginModules set a Group of name "Roles".

Custom Collection null when passed through WCF Service

We have some custom collections such as this:
[Serializable]
public class OccupationCollection : Collection<Occupation>
{
}
We use these in objects like the following:
private OccupationCollection _occupations;
public OccupationCollection CurrentOccupations
{
get
{
if (this._occupations == null)
return new OccupationCollection();
else
return _occupations;
}
}
Now we are making a call to a WCF service, passing objects that contain these type of lists. The lists always end up being null in the service.
I'm pretty sure this has somthing to do with serialization or something like that.
What would the simplest solution that would require minimal changes to the existing objects to get this to work?
Have you hosted your service over HTTP?
If yes, can you use fiddler to check the HTTP traffic and confirm whether serialized version of the parameter is being sent across the wire? If yes, there can be a parameter mismatch in contract between server and client.
Also is the object holding OccupationCollection decorated with Serializable/DataContract attribute? If you have DataContract attribute, ensure that the properties that need to be serialized are marked with Datamember attribute.
More details out here..
http://blog.functionalfun.net/2009/09/if-your-wcf-service-is-unexpectedly.html

Multitenant/Shared Application system, how to maintain multiple tentant-specific identifiers?

I have a multi-tenant system where each tenant shares the same instance of the codebase, but has their own databases.
I'm using RavenDB for persistence, with a standard c# facade/BLL backend wrapped with Asp.net WebAPI, and I'm finding that at every lower level operation (deep within my business logic classes) that touch the datbase, I need to pass in an identifier so that my RavenDb client session knows which database to operate against.
When the user authenticates, I resolve the appropriate database identifer, store it in the session manager. Every call against the Web API layer passes in a session ID which resolves the database ID in the backend, which is then used to pass into every single facade/BLL call.
All my dependencies are handled via an IoC container at the WebAPI level, but i can't pass in the database ID at this phase because it can be different for every user that is logged in.
this, of course is getting tedious.
can someone give me some guidance as to what I can do to alleviate this? Maybe perhaps some sort of policy injection/AOP solution?
a rough sample of my backend code looks like..
public class WidgetService()
{
private WidgetBLL _widgetBLL;
private ISessionManager _sessionManager;
public WidgetService(WidgetBLL _widgetBLL, ISessionManager sessionManager)
{
_widgetBLL = widgetBLL;
_sessionManager = sessionManager
}
public Widget getWidget(string sessionId, string widgetId)
{
string DbId = sessionManager.ResolveDbId(sessionId)
return _widgetBLL.GetWidget(string dbId, string widgetId);
}
}
public class WidgetManager()
{
public GetWidget(string dbId, string widgetId)
{
using (IDocumentSession session = documentStore.OpenSession(dbId)
{
var widget = session.load<Widget>(widgetid);
}
return widget;
}
}
the DBID is the identifier for that particular tenant that this particular user is a member of.
You need to change how you are using the session.
Instead of opening and closing the session yourself, do that in the IoC code.
Then you pass a session that is already opened for the right db.