A facade to hide authentication details from Java web service - java

I'm building an UI client that uses a service API that behind the scene uses Web services. One of the API services looks like this:
interface UserService {
List<User> findUsers(User loggedInUser, UserSearchParameters searchParameters, PagingParameters pagingParameters) throws AuthenticationFault, InvalidIndexFault;
void removeUser(User loggedInUser, User userToRemove) throws AutheticationFault;
void addUser(User loggedInUser, User newUser) throws AuthenticationFault;
}
The loggedInUser is the user on who's behalf the method is called. AuthenticationFault is a checked exception. There's like 20 of these service interfaces. What I would like to do is implement a facade that hides the loggedInUser parameters and AuthenticationFault exceptions. The facade implementation would call these methods with the user that is currently logged in the client.
I would also like to do some cleaning with the other checked exceptions too. As you can see there is a InvalidIndexFault exception that is thrown when client tries to retrieve page -1 but that is a programmer error and I don't want to have it as a checked exception.
Currently what I've done is always rethrow a RuntimeException for exceptions that I don't like, but if I later change my mind it's a lot of work changing that later. This also feels like code duplication. Other programmers have just swallowed exceptions and logged them which is totally horrible. Most of the time if there is an exception I want to bubble it up to error handler in the ui that displays an error.
There's been a few solutions that have come to my mind:
Java dynamic proxy
Code generation
I haven't gotten around to try out those solutions and figured I might as well ask here first. How do you suggest I would implement this? The environment is Java 6 and build tool is Maven 3 if that helps.
PS. If you answer this, please say more than "pick number 2" :) Any tips and other implementation details are welcome.
As a clarification retrieving the currently logged in user is not an issue so you don't have to help me with it. I currently hide it behind an interface and use IoC to inject it around. Behind the scenes it uses ThreadLocals

I guess this would be the perfect use case for
Java Dynamic Proxys
Thread locals
To elucidate:
First, create your Facade Interface :
interface UserServiceFacede {
List findUsers(UserSearchParameters searchParameters, PagingParameters pagingParameters) throws AuthenticationFault, InvalidIndexFault;
void removeUser(User userToRemove) throws AutheticationFault;
void addUser(User newUser) throws AuthenticationFault;
}
Next you implement your InvocationHandler :
public class UserHandler implements InvocationHandler{
private final UserService service;
public UserHandler(UserService service) {
this.service = service;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
....
// Based on the method argument, call the appropriate function on the actual service
// object
....
}
}
You then create the Proxy object like so :
UserServiceFacade uProxy = (UserServiceFacade)Proxy.newProxyInstance(UserHandler.class.getClassLoader(),
new Class[] { UserServiceFacade.class},
new UserHandler(userService));
The first argument is the classloader, the second is the list of interfaces the Proxy must confirm to and the third is the handler object
Now the question is how do you get a handle onto your loggedinUser. This is where ThreadLocal comes in.
Create a ThreadLocal static variable that holds the loggedin user. Then set the current user into the ThreadLocal before invoking the proxy
private static final ThreadLocal loggedinUser = ...;
...
...
loggedinUser.set(currentUser);
// Create a user Proxy object as mentioned above..
uProxy.findUser(searchParams, ..);
...
Retrieve the User from the ThreadLocal inside the invoke function of the handler. Now inside the handler, you have access to both the loggedinUser (using loggedinUser.get()) as well as the user service object (You have passed in the service object into your handler's constructor)
As far as how you handle exceptions are concerned, WHat I would do is generally keep throwing a subclass of RuntimeExceptions. Then catch these at the periphery layer of your app. By periphery layer I mean, entry point into your app/library. If you were developing a webbApp this would be your Servlet.

Related

IllegalStateException with Hystrix

I am new to Hystrix. I am trying to use it with Spring AOP. The following details what I am trying to achieve.
There is a "ServiceClass", into which some RestClient class is injected. I am using Spring. Now, I want to use Hystrix together with Spring AOP so that method calls to the RestClient from the ServiceClass could be made synchronously or asynchronously.
What I have done so far is as follows.
created a class "MyCommand" that extends HystrixCommand implements MethodInterceptor
implemented a method "execute(MethodInvocation m, String mode) in it as follows:
protected Object execute(MethodInvocation m, String mode){
this.mode = mode;
this.method = m;
return execute();}
in the (overridden method) "invoke"
public Object invoke(MethodInvocation m) throws throwable{
try{
execute(m,"Sync");
} catch(Exception e){
e.printStackTrace();
}
}
This "MyCommand" is being set as the AOP Interceptor for the "ServiceClass" in the spring-config file.
Now, the issue is; in my "Main" application when I retrieve the "ServiceClass" from the ClassPathXmlApplicationContext and invoke one method, it works fine. But if I try to invoke two of the methods of the "ServiceClass" it throws the following exception:
*java.lang.IllegalStateException: This instance can only be executed once. Please instantiate a new instance.*
Code snippet:
ServiceClass srvc = (ServiceClass) ctx.getBean("proxy");
srvc.getRequest();
srvc.postRequest();
I have spent almost three days trying to figure it out the cause and solution for this exception but without any good. Please help me get this right. What am I missing?
As always,
Thanks in advance
A HystrixCommand object can only be used once, because it contains useful state information after it is executed that can be used for further processing. For example, if you wanted to do special handling after the fact if the call to run() timed out, you could do the following:
public class MyHystrixCommand extends HystrixCommand<Object> { ... }
MyHystrixCommand command = new MyHystrixCommand();
command.execute();
if(command.isResponseTimedOut()){
//do post processing
}
If you could invoke execute() multiple times, especially from multiple threads as would happen if you had multiple consumers of your REST endpoint, you would have no way of knowing which invocation was the one that timed out when you queried the command for its state.

Where should I place validation code that requires access to database?

I have a Spring MVC webpage that is used for password resets. This requires us to do the following validation workflow:
provide username OR email
if email is provided make sure it is valid format (ex: #Email)
Check that User exists by:
3a) Trying to load the user from the database via username
3b) if loading by username returns null, try to load the user from the database via email
After loading, check that user is not locked out: user.isLocked()
Currently I have all of these Validations inside a org.springframework.validation.Validator
However this requires my Validator to have access to the UserService object so it can load users. This causes the user to be loaded 2x, once by my validator and a second time by my Controller so it can invoke .resetPassword(User).
Question: Where should I be checking item #3 ?
Are those validations better suited for the Controller ? If I leave validation as is, can I return the User from the Validator (it has void method due to Validator interface)?
In my opinion, steps 3 and 4 don't belong to view layer (in particular, to validation performed by controller) at all.
These steps are essential parts of business logic for this scenario, therefore they should be implemented in service layer.
Your service layer should provide a method such as
public void resetPasswordByUsernameOrEmail(String usernameOrEmail) { ... }
and these steps should happen inside this method, along with resetPassword(User).
If you need, you can make controller aware of result of this method by throwing an exception, returning a boolean or an enum (if you want to distinguish between different error conditions).
To answer your questions in order:
You should do the checking for a User's existence in the UserDao.
No, these validations should not be in the Controller. The Controller shouldn't know anything about validation, otherwise it would be trying too do to much and we'd be guilty of low cohesion.
Since you're using an interface that defines a method with a void return, if you wanted to return a User you would have to do one of the following:
Create your own method in your Validator implementation. The disadvantage of this is that you could not use polymorphism as effectively since you would depend on a method not defined in the Interface.
Make your own Validator (possibly make your own Interface that extends Spring's Validator interface and defines the method you want). This is probably what I would choose.
Maybe that's a duplicate: Spring MVC Bean Validation
Another solution would be this:
In one of the projects I worked, we used to have a SpringBeanUtil class. It would get the WebApplicationContext, and get the bean needed through a static method.
It's kind of ugly, but helped on these kind of problems.
Use at you own risk.
public class SpringBeanUtil implements ApplicationContextAware{
private static ApplicationContext APPLICATION_CONTEXT;
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
APPLICATION_CONTEXT=applicationContext;
}
public static Object getBean(String name){
return APPLICATION_CONTEXT.getBean(name);
}
public static <T> T getBean(Class<T> type){
return APPLICATION_CONTEXT.getBean(type);
}
}

How should I pass subject/principals/roles between application layers in Java?

I currently have a number of web applications which access a common service running in JBoss 5.0. The service is very simple, using Guice and POJOs. The web applications are authenticated and know who the user is and what roles they have. When calling the service how should I pass this authentication information to the service?
It would seem the simple approach is to simply add a parameter to the interface to take the user information. Possibly a Subject. But this has the downside of cluttering up the interface with contextual information that isn't specific to the job in hand.
void doSomething(Subject subject, ...) {
}
The alternative I have seen is to use ThreadLocal storage, put the user information in there before making the call and make this accessible via some utility class that the service can use. This cleans up the interface but hides the fact that the client of the service has to set the user information before making the call.
Is there another way of doing this? I get the feeling the AOP may be of use here too but can't quite see how. Is there some "best practice" I am missing? Would EJB help?
This cleans up the interface but hides the fact that the client of the
service has to set the user information before making the call.
True, but if you need to pass something to a particular method across the application then you are defeating the purpose of using Dependency Injection. It's there so that you don't have to pass a bunch of services and objects to other services and objects and so forth, they are created with everything they need.
Is there another way of doing this? I get the feeling the AOP may be
of use here too but can't quite see how. Is there some "best practice"
I am missing? Would EJB help?
The other way of doing this would be to use a single filter on every Servlet that calls the services that need the Subject / User. Set the user in the filter, and clear the user at the end in a try-finally block. In fact, OWASP Esapi uses this style when setting their ThreadLocalUser, it allows the User to be available in every part of the application.
Something like this:
#Singleton
public MyUserFilter extends FilterOfTheMonth {
private final Provider<Authenticator> authProvider;
#Inject
MyUserFilter(Provider<Authenticator> auth) {
this.authProvider = auth;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws java.io.IOException, ServletException {
try {
// Authenticate and SET the current user utilizing the request and/or
// session objects
authProvider.get().authenticateUser(HttpRequest currentRequest);
// Continue on here along the servlet chain
... other processing
} finally {
authProvider.get().getRidOfCurrentUser();
}
}
}
Have you considered moving the authentication process to the common service? Then you only need the session ID in the common service to identify all information about the user the request is coming from.

Is there a way to share data between interceptors and actions in the play framework?

In a Play! controller, I can create an interceptor method that will process every request before it arrives to the appropriate action.
public class Admin extends Application {
#Before
static void checkAuthentification() {
if(session.get("user") == null) login();
// otherwise,
User loggedOnUser = User.find("byUsername", session.get("user"));
}
public static void index() {
// any way to access loggedOnUser ?
List<User> users = User.findAll();
render(users);
}
…
}
Is there a way to set a value in the interceptor and access it in the action? Sort of like request.setAttribute() in servlets?
You can use renderArgs parameter from Controller (see here) or you can store the value in the Cache (we can assume that as the value was added miliseconds ago, your value will be available while in the same request).
Interceptors and actions share the same request context (request, response, session, etc). As stated above, you may elect to use renderArgs, but keep in mind that these values will be available in your views, which may not be what you want. If you want to keep the state between your interceptor and actions, just use the request.args hash instead.

What are my options if I want to proxy all service calls so that I can log them appropriately without an explicit call to a logger?

Instead of trying to get developers to remember to log each service method call and/or exception, is there a pattern that will proxy to the right service method, in the process logging the call, and trapping/logging any exceptions that are thrown before returning a response back to the caller? I know there is a proxy pattern, but I'm not sure it does what I need it to... if there is a way to create an interface that will better enforce a logging requirement, then I'm open to that as well.
Logging is a cross cutting concern. You can use AOP for that. Have a look at AspectJ or Spring AOP.
You could consider using Dynamic proxies for implementing your service layer.
It uses the reflection api so all method calls to your service code will go through a single "invoke" method where you can log service calls, method parameters and exception messages.
public class MyServiceProxy implements InvocationHandler {
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new MyServiceProxy(obj));
}
public Object invoke(Object proxy, Method m, Object[] args) {
// Log method name , parameters etc.
try {
method.invoke(proxy, args) ;
}
catch(InvocationTargetException e) {
// log your exceptions and do other things
throw e.getTargetException();
}
}
Where you call your service, you would instead do this
MyService myServiceRef = (MyService)MyServiceProxy.newInstance(new MyService());

Categories

Resources