How to test code that needs passed HTTPServletRequest - java

I'm running some Scala code (with Java socialAuth library) that requires an HTTPServletRequest to be passed in as a param.
def myClass(prov: String, site: String, request: HttpServletRequest): {
//some initial code here
val session = request.getSession()
session.setAttribute(/*some params*/)
//code continues...
}
So the HttpServletRequest seems like a really cool way of storing session variables and passing a session between methods. However, I'm not quite sure how to test this code, as I don't really understand what the HttpServletRequest interface is.
I've done a bit of research, but I was wondering if anyone could clarify for me. HttpServletRequest is an interface, which means it can't be instantiated on its own. How, then is it used in code?
EDIT: as in, when a method takes an HttpServletRequest as a parameter, what implementing class is usually passed in?
FOLLOWUP: Based on the answers given, HttpServletRequest is implemented differently by different servers; Ireeder pointed out, for example, that Apache even has multiple implementations. How, then, does code specify that the server needs to use its implementation? In other words, lets say I have test code that uses myClass:
def otherClass(){
val site = "www.example.com"
val provider = "twitter"
val mockRequest = mock(HttpServletRequest.class) //using https://code.google.com/p/mockito/. (eclipse throws error..not too sure about syntax but throwing up this example quickly, so will edit later)
myClass(provider, site, mockRequest)
}
I assume this is OK for testing, as Mockito creates a mock object, but when otherClass() needs to be implemented on a server, how is its code adjusted? (Sorry, I'm a bit new at this, so bear with me...) If val mockRequest needs to be implemented with whatever HttpServletRequest implementation is used by the server (Apache, Oracle, etc), how does the user specify this in otherClass? Will something like this change:
//deleted line: --val mockRequest = mock(HttpServletRequest.class)
//changed line: myClass(provider, site, mockRequest) to below:
myClass(provider, site, javax.servlet.http.HttpServletRequest)
be interpreted and implemented correctly by the server?

Container implementers like Oracle or Apache extend the HttpServletRequest interface with their own implementations that actually do something. You could do the same for your testing, or use something like Mockito to mock it.
The only time you should be providing an implementation of an HttpServletRequest is at unit testing time, not when your code is running in a servlet container. The container will pass you its own HttpServletRequest, and your code should not care about the exact implementation of that interface. It should only use the methods provided by the HttpServletRequest interface so that it is independent of the container it is running in.
If you need to test the behavior of your code when it's running in servlet container, you can do manual testing, or use a testing framework that makes HTTP requests, like HttpUnit

Spring users can use the class MockHttpServletRequest (JavaDoc)

Related

How to force developers to write CustomAnnotation before each api Springboot

How can we force developer to write Developed Custom-annotation on rest api
Example :
We Developed annotation Called : ValidatePermission
what we need to do , displaying runtime error for developer that he missing annotation #ValidatePermission on API , when he tried to write new api
#ValidatePermission
#GetMapping("/details")
#PreAuthorize("hasAuthority('902')")
public ResponseEntity<CustDtlsInqDto> getCustomerDetails(#CurrentUser UserPrincipal currentUser,
#RequestParam(name = "poiNumber", required = false) String poiNumber,
#RequestParam(name = "cif", required = false) String cif) {
return ResponseEntity.ok(customerService.getCustomerDetailsByPoiOrCif(currentUser.getId(), poiNumber, cif));
}
Annotations usage cannot be forced in any way before or on compilation (at least I am not aware of any technique, feel free to correct me).
The only way to go is to perform a check-up during the unit testing phase. Simply write an unit test that scans through the REST API definition beans and its public methods (or annotated) to check up using teh Reflection API whether an annotation from a particular category (implementation details up to you) is present within the formal parameters of methods.
Gits Github: Find all annotated classes in a package using Spring
Baeldung: A Guide to the Reflections Library
Something looks to me weird in this approach.
So you say:
...displaying runtime error for developer that he missing annotation #ValidatePermission on API
Based on this phrase, let me suggest an alternative:
So the developer that runs the project locally (during the debugging session or maybe tests) should see an error if he/she didn't put the annotation on the methods of rest controller, right?
If so, Why don't you need the developers to put this annotation?
The main idea of my suggestion is: Why not letting spring to do it for you automatically?
You could implement some kind of aspect or if you don't want to use a spring aop and prefer 'raw plain spring', BeanPostProcessor, that would 'wrap' all the methods of class annotated with RestContoller (by creating a run-time proxy) and before running a controller method will executed the logic that was supposed to be supported by the annotation?
In the case of Web MVC, another approach is to implement an interceptor that will be invoked automatically by spring mvc engine and you'll be able to execute any custom logic you want there, you'll also be able to inject other beans (like auxiliary services) into the interceptor.
Read this article in case you're not familiar with these interceptors, you'll need preHandle methods as far as I understand.

Java: How do I unit test where there are encapsulated injected or generated dependencies?

SUMMARY:
I have a self-contained class for performing a proxied login and then filling a HttpServletResponse object with authentication content a browser can use. When testing my code, how can I provide mocked services into a class that has no setters?
DETAILS:
I've severely edited my proxied login code into this snippet.
It asks the server for a login form.
It sends back the credentials.
It gets the server's approval and passes it to the browser
(response).
The trimmed code looks like this:
private static final Log log = LogFactory.getLog(MyClass.class);
#Inject()
private UserService userService;
public void performProxyLogin(HttpServletResponse response,
UserDTO userDTO, String url) {
String username = getUsername(userDTO);
String password = getPasswordFromUserService(username);
// MyRequest only has data, organizing a Http Request.
MyRequest myRequest = prepareInitialGetRequest(url);
// processURLRequest() encapsulates use of HttpURLConnection.
// MyResponse only has data, organizing a Http Response.
MyResponse myResponse = processURLRequest(myRequest);
myRequest = prepareLoginRequest(myResponse, username, password);
myResponse = processURLRequest(myRequest);
// Transfer data into the response, and from there into the browser.
fillResponseWithProxiedResult(response, myResponse)
}
To make this work I think I need to inject a mocked Log or LogFactory, a mocked UserService, and a way of getting a mocked HttpURLConnection.
However, all of the advice I've seen involves code with setters, which the test suite can use to plug in mocked objects.
How do I provide my class its needed mocked objects?
Bite the bullet and provide a package-private setter for this field.
If you want to use mocks, there's no value in letting the injection framework set up a mock which you can inject, since you're adding more ceremony and overhead to the set-up of your test.
If you want to validate that you have a service injecting correctly, you wouldn't want to use mocks at all (think "integration test" with real or pseudo-real components).
Many of the other answers hint at it, but I'm going to more explicitly say that yes, naive implementations of dependency injection can break encapsulation.
The key to avoiding this is that calling code should not directly instantiate the dependencies (if it doesn't care about them). This can be done in a number of ways.
The simplest is simply have a default constructor that does the injecting with default values. As long as calling code is only using the default constructor you can change the dependencies behind the scenes without affecting calling code.
This can start to get out of hand if your dependencies themselves have dependencies and so forth. At that point the Factory pattern could come into place (or you can use it from the get-go so that calling code is already using the factory). If you introduce the factory and don't want to break existing users of your code, you could always just call into the factory from your default constructor.
Beyond that there's using Inversion of Control. I haven't used IoC enough to speak too much about it, but there's plenty of questions here on it as well as articles online that explain it much better than I could.
If it should be truly encapsulated to where calling code cannot know about the dependencies then there's the option of either making the injecting (either the constructor with the dependency parameters or the setters) internal if the language supports it, or making them private and have your unit tests use something like Reflection if your language supports it. If you language supports neither then I suppose a possibility might be to have the class that calling code is instantiating a dummy class that just encapsulates the class the does the real work (I believe this is the Facade pattern, but I never remember the names correctly)]

Accessing HttpServletRequest object in a normal Java class from Spring

I have a normal Java class in a Spring MVC 3.06 web application.
In this class I would like to inject or get hold of the HttpServletRequest object in a method.
I know I can pass this around, but I was wondering how can I get hold of the request without passing it in to the method. Perhaps using annotations or similar?
Also, what are the "real" concerns with getting hold of the request this way, except some peoples opinions of it being ugly coding. I mean, is it unstable to access it this way?
Preferably non application server dependent way.
I have seen
(HttpServletRequest) RequestContextHolder.getRequestContext().getExternalContext().getNativeRequest()
but this doesn't seem to work for Spring MVC 3.06 . RequestContextHolder doesn't have the method getRequestContext().
Use
((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
I'm not sure where you got RequestContextHolder.getRequestContext(), that's completely wrong.
is it unstable to access it this way?
No, it's stable enough, assuming you're always running the code as part of an HttpServlet request thread. The main issue is that yes, it's ugly, and it makes your code hard to test. That is reason enough not to use it.
If you must use it, then decouple it from your code, e.g.
public void doSomething() {
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
doSomething(request);
}
void doSomething(HttpServletRequest request) {
// put your business logic here, and test this method
}
#Context HttpServletRequest httpServletRequest =null;
use this

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.

How do I implement a front controller in Java?

I'm writing a very simple web framework using Java servlets for learning purposes. I've done this before in PHP, and it worked by consulting the request URI, then instantiating the appropriate class and method.
This worked fine in PHP, as one can do something like $c = new $x; $x->$y;. I'm unsure however of how to translate this to Java, or even if this is an appropriate way to go about it.
So far, I've tried:
Router router = new Router(request.getPathInfo());
String className = router.route(); //returns com.example.controller.Foo
Class c = Class.forName(className);
Object x = c.newInstance();
Foo y = (Foo) x;
y.doSomething();
This seems fine for a couple of routes, but doesn't seem like it would scale well, nor would it allow for sourcing routes from a configuration file.
How should I make it work?
Get hold of actions in a Map<String, Action> where the String key represents less or more a combination of request method and request pathinfo. I've posted similar answer before here: Java Front Controller
You can fill such a map either statically (hardcoding all actions) or dynamically (convention over configuration, looking up classes in a certain package, or scanning the entire classpath for classes with a certain annotation or implementing a certain interface).
And just stick to Servlet. The Filter isn't there for. At highest use it to forward the request to the controller Servlet. In the Servlet, just implement HttpServlet#service().
I would use a Servlet Filter as Front Controller. The router would connect paths with request dispatchers. In the doFilter method you would convert ServletRequest to HttpServletRequest, extract the request path and match it against the registered mappings. The result of this mapping is a request dispatcher you would dispatch the request with.
In pseudo code:
doFilter(ServletRequest request, ServletResponse response) {
httpServletRequest = (HttpServletRequest) request;
path = httpServletRequest.getRequestURI();
dispatcher = router.getTarget(path);
dispatcher.dispatch(request, response);
}
Depending on your need the default routing mechanism of the Servlet API could be sufficient.
Not quite sure what you're after but you might want to take a look at Java servlets. Granted many web frameworks are abstracted above plain servlets, but it's a jolly good place to start learning about Java web apps if you ask me (which indirectly you did ;) )
Download the Java servlet specification here: Java Servlet Spec - it's quite interesting.
How should you make it work? However you want it to. If you're just doing it for learning purposes, whatever you do will be fine.
I would suggest having all your actions implement the same interface though (maybe extend Servlet) so that you don't have to compile in all different classes.
Then you can essentially do what you're doing, except that your cast to Foo becomes a cast to Servlet and then you don't have to have a special case for all your different classes.
You can then also load up the routes from configuration (maybe an XML file).
Essentially what you're doing is implemented by the Struts 1 framework so it might be worthwhile reading up on that (it's open-source so you can also look at the source if you want).

Categories

Resources