Get header from request in service layer of Spring Boot application - java

Is there any way in spring boot to grab header from request in any point of application?
Some static stuff will be great.
Please, be aware that #RequestHeader does not work for me since I need this value on service layer.

You can inject HttpServletRequest object in your service layer like this :
#Autowired
HttpServletRequest request;
private void method() {
request.getHeader("headerName");
}
but remember, that bean HttpServletRequest has HTTP request scope. So, you can't inject that into asynchronous methods etc, because it will throw Runtime Exception.
hope it helps.

I was searching the same question before, i found out that you can use header parameters in the RestController methods with #RequestHeader as you said. So why not direct them into your service layer methods:
#Autowired
ServiceLayerObj serviceLayerObj;
...
#RequestMapping
public YourReturnObj someRestServiceMethod(
#RequestBody SomeObj body,
#RequestHeader(value = "username") String username
){
return serviceLayerObj.yourServiceLayerMethod(body,username);
}

Related

get HttpServletRequest in Spring MVC?

I am using Spring MVC. I am not using Spring boot dependencies.
I created the AuthenticationSuccessEventListener class, this class implements the ApplicationListener interface.
How do I get the HttpServletRequest in the AuthenticationSuccessEventListener class? I tried many options, but I still could not find the answer to my question.
When trying to get the HttpServletRequest, I get an exception.
Message: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Who can, tell me please, what am I doing wrong?
#Component
public class AuthenticationFailureListener implements ApplicationListener<AuthenticationSuccessEvent> {
// This option doesn't work.
// #Autowired
// HttpServletRequest httpServletRequest;
// This option doesn't work.
// HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
#Override
public void onApplicationEvent(AuthenticationSuccessEvent a) {
}
}

How to read request headers from incoming message in a graphQL endpoint in spring boot application

I have a spring boot application running with a graphql endpoint that validates and executes queries and mutations, however, I need to read one header in the incoming message in order to pass its value to another endpoint. Is there a way in graphql to read these values? some sort of getHeaders or something like that?
GraphQL itself does not define any things related to how to expose it over the network , so it does not define any things related to get HTTP header.It is up to developers to use their ways.So, it depends on the underlaying technologies you use to serve GraphQL over HTTP.
Consider you use graphql-spring-boot and graphql-java-tools , and assuming that you does not customize GraphQLContext , you can try to add DataFetchingEnvironment argument to your resolver function and then get the GraphQLContext from it. You can then get HttpServletRequest from the context and access the headers :
public Foo resolveFoo(Map<String,String> input , DataFetchingEnvironment env){
GraphQLContext context = env.getContext();
HttpServletRequest request = context.getHttpServletRequest().get();
request.getHeader("content-type");
}
The solution by #Ken Chan was not working for me. GraphQLContext had no method named getHttpServletRequest.
Solved it by using GraphQLServletContext instead. You can change the code to:
public Foo resolveFoo(Map<String,String> input , DataFetchingEnvironment env){
GraphQLServletContext context = env.getContext();
String header = context.getHttpServletRequest().getHeader("content-type");
}
Apparently the type of the context is not standardized. I use SPQR, and in my case I discovered (via debug):
DefaultGlobalContext<ServletWebRequest> context = handlerParameters.getDataFetchingEnvironment().getContext();
context.getNativeRequest().getHeader("something");
Not a direct answer to your problem statement, but one can use a Filter to handle it before the request hits the resolver endpoints (if that's a requirement):
public class HeaderFilter implements Filter {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
final HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String headerVal= httpServletRequest.getHeader("<header string>");
try {
filterChain.doFilter(httpServletRequest, servletResponse);
} catch (IOException | ServletException e) {
//handle as you wish
}
}
These answers are too old, for latest versions. There are two ways (1) you can try to autowire one HttpServletRequest in your controller, such as
#Slf4j
#Controller
public class YourQueryController {
#Autowired
private HttpServletRequest request;
....
Then implement following logic to get header:
request.getHeader("Authorization")
(2) To make use of out-of-box support of RequestContextHolder over HTTP requests
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
val authorization = attributes.getRequest().getHeader("Authorization");
Google brought me this answer and unfortunately it was for Spring framework. Many use Spring framework but if you use Apache Tomcat with GraphQL integration like I do, you can do use this.
graphql.kickstart.servlet.context.DefaultGraphQLServletContext.DefaultGraphQLServletContext context = dataFetchingEnvironment.getContext();
jakarta.servlet.http.HttpServletRequest request = context.getHttpServletRequest();
String tokenBearer = request.getHeader("Authorization");
hth

Understanding REST APIs - What are Context and #Context?

I recently went through restful web services tutorial, but couldn't understand what a context is. Can someone explain what it it and also what #Context does?
JAX-RS provides the #Context annotation to inject 12 object instances related to the context of the HTTP request and they are:
SecurityContext - Security context instance for the current HTTP request
Request - Used for setting precondition request processing
Application, Configuration, and Providers -> Provide access to the JAX-RS application, configuration, and providers instances
ResourceContext - Resource contect aclass instances
ServletConfig - The ServletConfig instance instance
ServletContext - The ServletContext instance
HttpServletRequest - The HttpServletRequest instance for the current request
HttpServletResponse - The HttpServletResponse instance for the current request
HttpHeaders - Maintains the HTTP header keys and values
UriInfo - Query parameters and path variables from the URI called
It is a little confusing to have both an #Inject (or #Autowired in Spring) and #Context that does the same job, but it is hoped to bring more alignment to Java EE in the next edition. In the meantime, you will have to make do.
An interesting feature is that all of these instances can be injected as a field value or directly into the resource method.
An example of injection into the resource method parameter list:
#Path("/")
public class EndpointResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getAllHttpHeaders(final #Context HttpHeaders httpHeaders){
// Code here that uses httpHeaders
}
}
An example of injection into a field:
#Path("/")
public class EndpointResource {
private final #Context HttpHeaders httpHeaders;
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getAllHttpHeaders(){
// Code here that uses httpHeaders
}
}
If you want to know more, take a look at this series of articles answering the question What is #Conext in JAX-RS used for?
For an explanation about context in programming terms, have a look at this answer.
The JAX-RS API provides a #Context annotation. In general, such annotation can be used to obtain contextual Java types related to the request or response. Those types can be injected into classes managed by the JAX-RS runtime.
For example, to inject the HttpServletRequest in your resource method, you can do the following:
#GET
public Resonse foo(#Context HttpServletRequest request) {
...
}
Additional resources:
Types that can be injected with #Context
Jersey documentation about resources
context is a react Hook feature that helps to pass the data from one component to another without calling the props at each level ... it avoids prop drilling. by defining the provider in one context component and then you can call everywhere and every time when you need.
REST is an architectural style and one of the way to implement web-services. (Other is SOAP). There are many implementations of REST architecture and one of them in java is Jersey (https://jersey.java.net/)
#context is annotation in Jersey framework. It's a class from jax rs jar. (https://jersey.java.net/apidocs-javax.jax-rs/2.0.1/javax/ws/rs/core/Context.html)

CDI and HttpRequest

I am using a helper class in a servlet to remove some code from the servlet itself. I am injecting this helper class in the servlet with the CDI #Inject and this is also marked as #RequestScoped bean. Since this helper class is used to remove some code from the servlet I need access to the httprequest, response and session in this class. Is there a way to make these available via injection? I tried to use #inject on a field of type
HttpServletRequest but I get an error from WELD.
There are a couple of alternative solutions to this.
You could pass the HttpServletRequest to the helper. I mean instead of the helper being:
#Inject HttpServletRequest request;
public Xxx doSomeHelperWork() {
// use request
}
Make it:
public Xxx doSomeHelperWork(HttpServletRequest request) {
// use request
}
Use the DeltaSpike servlet module which can handle the injection of HttpServletRequest.

cache controller response

I'd like to use memcached to cache the response produced by my controllers. The controllers themselves are Grails controllers, but there's nothing really Grails-specific about the problem. If I could figure out how to solve this problem in a Spring MVC, Struts (or similar) application, I should easily be able to migrate the solution to Grails.
Ideally, I'd like to identify the controller methods that are eligible for caching using Java annotations. Is anyone aware of an existing solution for this problem? I should emphasise that I'm not interested in using any caching technology other than memcached.
Thanks,
Don
The Simple Spring Memcached library the previous poster linked to would actually accomplish what you need to do. It doesn't limit itself to just DAO methods. You could annotate a controller method to cache it's response just as easily as annotating a DAO method.
So, if you have a Controller named SimpleController and you wanted to cache the response of that controller, you could do the following
public class SimpleController implements Controller {
#ReadThroughSingleCache(namespace = "SimpleController", keyIndex = 0, expiration = 3600)
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
return new ModelAndView("index")
}
This will cache the response of the controller in Memcached for an hour and any request that comes in that matches the same request will return the cached response.
Aaron, braveterry,
Thanks for suggesting my project: http://code.google.com/p/simple-spring-memcached/
Don, Aaron is correct that SSM is not limited to DAO methods, however there are a few caveats for his example:
I don't think HttpServletRequest's toString() method would produce a good key
You would need to make sure that ModelAndView is Serializable
That being said, there's no reason you can't delegate to another bean that has an appropriate signature
Here's some code as an example:
public class SimpleController implements Controller {
private BeanWithAnnotatedMethod bean; // Injected resource
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
Object keyObject = Helper.generateAppropriateKey(request);
String result = bean.annotatedMethod(keyObject);
return new ModelAndView(result)
}
Would something like this do the trick? http://code.google.com/p/simple-spring-memcached/

Categories

Resources