Avoiding repetitive arguments in Java EE - java

TL;DR The question is about avoiding repetitive arguments in method signatures without performance degradation.
public void foo(Context context, Config config, Request request);
void helper(Context context, Request request);
void otherHelper(Context context, Config config, Request request);
I need signatures like this:
public void foo(Request request);
void helper(Request request);
void ohterHelper(Request request);
Configuration won't change very often, some arguments will be request scoped. Caches may have a broader, conversation scope etc.
I want to apply this idea to Java Enterprise environment.
It should be a bean with injected field config that calls other beans f and g (also with fields config) and concatenates results as in example. It should extend to many more fields like config (e.g. context or cache), but only request data from client is allowed in actual method signature (in this example there is none to be concise).
Lifecycle of all config fields should be managed so that all beans in see same config value for the duration of some externally managed scope (e.g. request to facade).
There may exist an EE pattern that solves this problem.
I am explicitly not looking for solutions using ThreadLocal as I want to be able to run tasks in parallel (if at all possible). I am also not looking for AOP and scoped beans (constant allocation and work for GC, I have done profiling before in similar situation).
I have feeling that solution might be an "lost art" today and may be as simple as proper container management (with dependency injection) of pooled of session beans. The trick would be for container to know how to manage lifecycle of g and h within f while injecting (or mutating) all fields when a scope changes (e.g. new request, new conversation).

Assuming some way to get the config and context, set your current methods to private and create a public convenience function:
public void foo(Request request) {
Context context = getContext();
Config config = getConfig();
foo(context, config, request);
}

Related

What is the recommended way to pass state information to an HTTP interceptor?

I am trying to perform logging of all HTTP outbound requests from my application. However, I need the HTTP interceptor to have access to some meta-data of the HTTP calls. This data is set manually for each separate type of HTTP call in the app logic itself. Now, there are two apporaches I have found so far to pass this data on to the interceptor:
Include this metadata in a temporary HTTP header, log it when the call is intercepted, remove the header, make the call
Store the data in a static ThreadLocal variable, retrieve it in the interceptor and clear the ThreadLocal storage
Although both these methods work fine, there are some reservations I have regarding both methods. For the first method, it seems unwise to alter the HTTP request itself as, in case, the interceptor is not working/not being used, the metadata will be passed on to the remote server. For the second method, the use of ThreadLocal comes associated with problems of heap memory management as too many threads might eat up heap space.
Is there any other standard/recommended method to approach this problem? If not, which of the above mentioned methods would be better suited at addressing this problem statement?
An alternative method in Spring is to have a Bean with bean-scope set as "Request". Singleton scope beans are not thread-safe, however, with a Request scope, a Bean is established only within the context of a single HTTP-Request and as such. Such a Bean is instanitated at the start of an HTTP request and its state persists the entire duration of just that HTTP request. The syntax for this is:
#Bean
#Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator requestScopedBean() {
return new HelloMessageGenerator();
}
or, alternatively, a shorter version of the same code:
#Bean
#RequestScope
public ScopedBeanClass requestScopedBean() {
return new ScopedBeanClass();
}
The ScopedBeanClass may now be used to set and read values in a thread safe manner at any point during the lifetime of a single HTTP Request after which the Bean is cleared/reset in the next request (possibly from a concurrent Thread)
Request scope is one of 4 web-aware scopes that can be used. The other scopes are: Session Scope, Application Scope and WebSocket Scope
More info on these scopes is present here
Please try spring cloud zuul. In its zuulFilter, you can log every request, then re-dispatch request to target. The spring cloud gateway has same effect.

How to call a Servlet/Filter before a JSP is executed in CQ5?

In a Spring MVC application we have a Controller that would execute before calling the JSP. The Controller would prefetch some values from the database and set them in the model and forward the control to JSP.
How do I implement this feature in CQ 5? I want the SlingFilter to execute before the JSP is executed. And the JSP is not a page component but a component that appears in the side kick.
Note:
I can do this by writing my own SlingSerlvet that would prefetch my required values and use the RequestDispatcher to forward to the JSP.
But by this method I would have to go through a URL like "/bin/.*". And this is again at a page level I want this kind of functionality at component level.
So to answer your specific question, if you want a filter to be executed before a component is called you would create a filter that is listening to Component level filter scope.
See
http://sling.apache.org/documentation/the-sling-engine/filters.html
You would then have your filter change the incoming request to a SlingServletRequest and determine if the target resource is the one that you are looking for.
However this filter would be executed on every single component that is being included on a page. The reverse process of this that may be useful to you is the ResourceDecorator.
http://sling.apache.org/documentation/the-sling-engine/wrap-or-decorate-resources.html
These are executed when the resource is identified, prior to the servlet and filter calls, which would allow you to verify if a resource is a type that you are interested in, and then allows you to add additional information to the resource object.However this is, once again a service that would be applied to every resource that is identified.
However, if what you are looking for is a filter that is only executed for a specific path, then no. Sling doesn't do that. You mentioned Spring MVC and Spring MVC works on a completely different concept of MVC then what Slings version of MVC does.
EDIT
So in a traditional web app, the servlet would be at a fixed position and all filters are applied prior to the call to that servlet. In Sling you are dynamically wiring servlets together to generate the resulting page. So each time that you are in a servlet and call directly or indirectly the request dispatcher, it's executing the resolution process again and applying a series of filters again before the new servlet is executed.
To prevent a high level filter that needs to applied only to the main request being applied on every single internal dispatch, they came up with the idea of contexts, or chains of filters that are applied at different times and associated with different types of includes.
Here is a basic filter that will log a message when it's called. I did this from memory so you'll need to dink with it.
#SlingFilter(scope = SlingFilterScope.COMPONENT, order = Integer.MIN_VALUE)
public class SampleFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(SampleFilter.class);
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
Resource res = slingRequest.getResource();
if (!(res == null || ResourceUtil.isNonExistingResource(res))) {
LOG.error("this servlet is called before resource {} at path {}", res.getName(),res.getPath());
}
chain.doFilter(request, response);
}
}
The important part of this is scope = SlingFilterScope.COMPONENT take a look at the page I had listed earlier and try out different combinations of slignfilterscope and you'll see how it's being applied at different times. scope = SlingFilterScope.REQUEST would be once at a top level on a per page basis.
JE Bailey's answer is correct as far as Filters are concerned, but I suspect your problem might be solved in a different way that better fits Sling's view of the world.
Sling promotes the use of OSGi services for business logic, and scripts should be a thin layer above that. Moving your logic to OSGi services and calling those from your scripts is the recommended way.
You might also have a look at Sling Models which can include processing steps (with #PostConstruct) before the rendering scripts kick in.
But by this method I would have to go through a URL like "/bin/.*".
You can also register a servlet against a resource type, as well as by path, e.g. (from the Sling documentation):
#SlingServlet(
resourceTypes = "sling/servlet/default",
selectors = "hello",
extensions = "html",
methods = "GET")
public class MyServlet extends SlingSafeMethodsServlet {
#Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
...
}
}
If you remove the "selectors", "extensions" and "methods" parameters on the annotation, this servlet would bind against all calls to sling/servlet/default without requiring binding against a set path.

How does an JAX-RS 'endpoint' behave when making a request?

There is something I am not sure I understand correctlty, therefore, I need help:)
I have seen this: example,
#Path("/resource")
public class Resource {
#Context
private HttpHeaders headers;
#GET
public void get(#Context UriInfo uriInfo) {
/* use headers or uriInfo variable here */
}
}
Does this mean that for each request the class that is transformed to 'endpoint' creates a separate thread? Because, otherwise, the headers information would not be accurate...
Can you please indicate a (short:) ) resource, not JAX-WS specifications, where I can find info about this?
I can't think of a shorter and more direct resource than the JAX-RS 1.1 spec itself. It is clear about what you are asking:
JAX-RS provides facilities for obtaining and processing information about the application deployment context and the context of individual requests. (...)
Context is specific to a particular request (...).
May I add for completeness: that context information is obtained through the #Context annotation. As of resources, the context information is only available to the ones annotated with #Path (also called root resources). Also, #Context can inject the following context types: Application, UriInfo, HttpHeaders, Request, SecurityContext and Providers.
And about the lifecycle (request/thread management):
3.1.1 Lifecycle and Environment
By default a new resource class instance is created for each request
to that resource. First the constructor is called,
then any requested dependencies are injected (context is one of those dependencies), then
the appropriate method is invoked and finally the
object is made available for garbage collection.
An implementation MAY
offer other resource class lifecycles, mechanisms for specifying these
are outside the scope of this specification. E.g. an implementation
based on an inversion-of-control framework may support all of the
lifecycle options provided by that framework.
The conclusion is:
Each request is, by default, handled by a different resource instance;
The context is injected at request time (thus a different context per instance).
Each specific implementation may change this lifecycle a bit, but the principles should be maintained (a context specific to each request).
As you can see, also, the spec says nothing about thread management. Since most JAX-RS implementations are Servlet-based, we can assume with certain safety that the each request instance goes to a different thread - as servlet containers are thread per request.

How do you cache data only for the duration of the http request using apache shiro in a servlet container?

More specifically, I find that I'm implementing a custom AuthorizingRealm, which declares template methods doGetAuthenticationInfo() and doGetAuthorizationInfo() for returning AuthenticationInfo and AuthorizationInfo objects, respectively.
However, when I retrieve the data for the AuthenticationInfo (a JPA entity) in doGetAuthenticationInfo(), I find that I already have the necessary AuthorizationInfo. Alas, there's no apparantly good way to hang onto this data, so I have to throw it out only to perform another JPA lookup when the authorization filter ultimately gets its turn in the filter chain.
Behold:
public class CustomRealm extends AuthorizingRealm {
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
UsernamePasswordToken userPassToken = (UsernamePasswordToken) token;
String username = userPassToken.getUsername()
User user; // Contains username, password, and roles
// Perform JPA lookup by username...
return constructSimpleAuthenticationInfoFromUser(user);
}
#Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// Look up user again? :(
...
}
}
I've considered a number of possibilities:
Use realm caching. The application will run in a distributed environment so there could be any arbitrary number of JVMs running. The default realm cache manager implementations don't solve all of the inherent problems and setting up an enterprise implementations seems out of scope for this project.
Use the subject's session. There is no server-side state and I'd like to keep it that way if possible. Perhaps you can force the session to behave like request scope, but I wouldn't know how to do so and that risks being obfuscated.
Implement my own Subject. There appears to typically be one Subject instance per request, but it's unclear how to bootstrap this and I would risk losing a lot of potential functionality.
Use the Shiro ThreadContext object. I could attach the data to the ThreadContext as a threadlocal property. Servlet containers generally follow a thread-per-request model, and the Subject instance itself seems to chill out here, awaiting its inevitable garbage collection. Shiro also appears to build up and tear down the context automatically. However, there's not much documentation on this and the source code is hard for me to follow.
Finally, the default WebSecurityManager keeps singleton instances of the CustomRealm around, one per JVM it seems. Simply setting some local instance property is not thread-safe.
This seems like a common data retrieval option and a typical deployment scenario. So, what am I missing?
Thanks!
I would go with option 4 - Using ThreadLocal object as your requirement clearly says that the object lifetime must be of http request.
Have a look at this discussion: When and how should I use a ThreadLocal variable?
ThreadLocal doc: http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html

Creating an application scoped bean in spring MVC

Good day Everyone,
I want to explain my current legacy application before i ask my question.
I have a servlet in a Tomcat in which i load a non-changing database table into memory in the init() using Hibernate. Because this is defined in the init(), it is called only once and its available across all subsequent requests to the servlet, this is used because it improved application performance because of less round trips to the database.
I have recently started to use Spring 3 and i want to change this set up (servlet class is now a controller) to Spring but my challenge is how do i create the ArrayList of domain object (as i do in the init()) at Spring load time for efficiency and have it available across all calls to the controller class without accessing the database every time a request comes in. If this is not possible, then what options do i have?
Any help would be very appreciated.
Pop that static data into the RequestInterceptor
public class RequestInterceptor extends HandlerInterceptorAdapter {
#Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
....
modelAndView.addObject("variableName", dataIWantToHaveAvailableAllOverThePlace);
....
super.postHandle(request, response, handler, modelAndView);
}
}
how do i create the ArrayList of domain object (as i do in the init()) at Spring load time for efficiency and have it available across all calls to the controller class without accessing the database every time a request comes in. If this is not possible, then what options do i have?
I would design this almost identically in your scenario as I would if the data was constantly changing and had to be read from the database on each request:
The controller is wired up with an instance of the MyService interface which has operations for retrieving the data in question.
Optionally, depending on if you separate your DAO layer from your service layer, the MyService implementation is wired up with a MyDAO bean.
The MyService implementation is marked as InitializingBean, and in the afterPropertiesSet() method you retrieve the one-time-load data from the database.
With this design, your controller does not know where it's data is coming from, just that it asks a MyService implementation for the data. The data is loaded from the database when the MyService implementing bean is first created by the Spring container.
This allows you to easily change the design to load the data on each request (or to expire the data at certain times, etc) by swapping in a different implementation of MyService.

Categories

Resources