Can I assign a servlet to a particular domain? - java

I have two CNAME-s pointed to the same server. I want to assign one servlet to the first CNAME and another one to the second CNAME. Can I do it in web.xml (or somehow else without manual parsing of ServletRequest)?

One of the idea to have a filter, and in it have a condition based on ServletRequest#getServerName() and dispatch the request to appropriate servlet, will do.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
...
[other processing/validations]
...
if(request.getServerName().equals("domain1.com"))
request.getRequestDispatcher("/servlet1").forward(request, response)
else
request.getRequestDispatcher("/servlet2").forward(request, response)
}
obviously, you could have <init-param> in your web.xml to dynamically set the domains, so that you could change these values based on your build profile.

Related

Java Servlet returns response to client before committing the database transaction

I use a 3rd party framework to process my requests by passing HttpServletRequest and HttpServletResponse into the framework. The database transaction handling is done separately from the framework like this:
public class MyServlet extends HttpServlet {
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
startTransaction();
framework.process(req, resp);
commitTransaction();
}
}
As it turns out, the framework writes the full response back to the client before the call to commitTransaction() returns. This creates possible race-conditions: The client might issue a follow-up request that runs in a second new database transaction that can't access the data added or updated in the first transaction, because it is not committed yet.
What are best practices to work around those kind of issues? I can't modify the behavior of the framework I'm using.
I suggest to use a ServletFilter for such concerns. It would look like this:
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
startTransaction();
chain.doFilter(request, wrapper);
commitTransaction();
}
However, you should add exception handling to the filter.

Change ServletRequest server name programmatically

I need to change the serverName of the ServletRequest object in my Grails controller. I'm having trouble figuring out how to do this since the serverName is a read-only property.
The most correct thing to do is probably to set up a clever filter or redirect which "fixes" your request URL before your servlet even gets involved. I know nothing about how to do that; you should ask on serverfault.com if you want to do that.
In java, you can fake it by creating your own subclass of HttpServletRequestWrapper which provides setServerName() and overrides getServerName() while delegating all other methods to the superclass. You can then provide a filter which creates an instance of your request and sends that one down the chain.
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
YourHttpServletRequest yourRequest =
new YourHttpServletRequest(request, newServerName);
chain.doFilter(yourRequest, response);
}
If I understand this correctly, CORS filter might help
I've used http://software.dzhuvinov.com/cors-filter.html in my previous project.
But you can also lookup on github for example https://github.com/eBay/cors-filter

Custom Java Servlet Filter

I'm writing my first ever javax.servlet.Filter impl and am trying to write the portion of the doFilter method where I prevent the request from going any further in the chain:
#Override
public void doFilter(ServletRequest request, ServletResponse response)
FilterChain chain) throws IOException, ServletException {
// Check for some stuff in the request...
boolean passesInspection = inspect(request);
if(!passesInspection)
// How do I prevent the request from going any further?
// I don't want it even getting to the servlet at this point!
}
How do I "block" the request from even making it to the listening servlet? Thanks in advance.
Simply don't call chain.doFilter(). The doFilter() call is what progresses the call. Don't call this and the processing stalls. This is not a good design however. You need to at least inform the caller

ClickJacking Filter to add X-FRAME-OPTIONS in response

In order to tackle clickJacking and blocking my site to be opened by iframe I have created a servlet filter in which I am adding below line to add "X-FRAME-OPTIONS" response header. But when I run page and see response headers of that page I never get this header in there. Any Idea why?
public void doFilter(
ServletRequest request, ServletResponse response, FilterChain chain
) throws IOException, ServletException
{
HttpServletResponse res = (HttpServletResponse)response;
chain.doFilter(request, response);
//Specify the mode
res.addHeader("X-FRAME-OPTIONS", "DENY");
}
You need to add the header before calling doFilter. By the time control returns from doFilter the headers and body have already been sent, so your addHeader is ignored.

How to get hostname in freemarker template?

I have SpringMVC project with Freemarker as view resolver. In some templates I have to generate links including hostname, but I can't get it.
In JSP I may to do like this:
`<% String hostName=request.getServerName();%>`
I tried to use "requestContextAttribute", but requestContext.getContextPath() returned path without hostname.
Where can I get full path or hostname separately?
We can do this in JSTL. Try adapting it in FreeMarker:
${pageContext.request.serverName}
It's important to understand that Freemarker is intentionally designed to not have knowledge of the context in which it's used, to make it more generic. That means that unlike JSPs, it has no access to the HttpServletRequest and Response objects by default. If you want it to have access, you'll need to provide it.
The way I solved this was to create a Servlet Filter to add the HttpServletRequest object as a Request Attribute which Freemarker does have access to.
/**
* This simple filter adds the HttpServletRequest object to the Request Attributes with the key "RequestObject"
* so that it can be referenced from Freemarker.
*/
public class RequestObjectAttributeFilter implements Filter
{
/**
*
*/
public void init(FilterConfig paramFilterConfig) throws ServletException
{
}
public void doFilter(ServletRequest req,
ServletResponse res, FilterChain filterChain)
throws IOException, ServletException
{
req.setAttribute("RequestObject", req);
filterChain.doFilter(req, res);
}
public void destroy()
{
}
}
You'll need to define this in your web.xml in order for it to work:
<filter>
<filter-name>RequestObjectAttributeFilter</filter-name>
<filter-class>com.foo.filter.RequestObjectAttributeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RequestObjectAttributeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Then, in my .ftl files, I can use the following:
${Request.RequestObject.getServerName()}
This code should work in freemarker:
<#assign hostname = request.getServerName() />
bar
But with freemarker it's better to get server name in java and push it into template as string.

Categories

Resources