How to get hostname in freemarker template? - java

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.

Related

Skip request filter for specific resource in jersey

Iam working on a jersey project and Iam using token authentication and am using ContainerRequestFilter for filtering all the request and checking whether it has a token with it, but the requests includes Login and registration request, but we need to skip these request.. How i can skip the filtering for login and registration requests? Is there any mechanism in jersey for achieving this?
thank you
As far as I know, there is no facility fo such a behavior using a raw deployment descriptor (web.xml).
However, if that was a custom filter, you can get it skip the excluded paths using a simple check on request url in your doFilter() method. But since you are using a third party filter, that won't be the way to go with but still can have this functionality achieved:
Change your third party filter (ContainerRequestFilter) mapping to another path rather than a wildcard one:
<filter-mapping>
<filter-name>containerRequestFilter</filter-name>
<url-pattern>/tokenizedpaths/*</url-pattern>
</filter-mapping>
Declare a new filter (you will see in a moment what it looks like), that will be mapped to a wildcard path to filter all requests and be delegated to dispatch requests to your containerRequestFilter only if the request path does not match the excluded path(s) (I've choosen register as a sample):
<filter>
<filter-name>filteringFilter</filter-name>
<filter-class>com.sample.FilteringServletFilter</filter-class>
<init-param>
<param-name>excludedPaths</param-name>
<param-value>/register</param-value>
</init-param>
</filter>
The FilteringServletFilter will look like somthing like the following:
public class FilteringServletFilter implements Filter {
private List<String> excludedPaths = new ArrayList<String>();
public void init(FilterConfig config) throws ServletException {
// You can declare a comma separated list to hold your excluded paths
this.excludedPaths = Arrays.asList(config.getInitParameter("excludedPaths").split(","));
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getRequestURI();
// If the url is one of excluded paths, then just continue with next filter
if (this.excludedPaths.contains(path)) {
chain.doFilter(request, response);
return;
}
// Otherwilse, forward the request to the needed filter
else {
request.getRequestDispatcher("/tokenizedpaths" + path).forward(request, response);
}
}
}

How do I detect user preferred language when showing my website , website is java jsp based

How do I detect user preferred language when showing my website , website is java jsp based. So I currently have
http://jthink.net/songkong/index.jsp
http://jthink.net/songkong/features.jsp
and was going to create a french version by recreating a french version in an fr subfolder
http://jthink.net/fr/songkong/index.jsp
http://jthink.net/fr/songkong/features.jsp
but do I ensure that if the user is using french as their computer language that they automaticaly get directed to the french version.
The trick is by working with "Accept-Language" sent by client (browser). Accept-Language is sent from the client in http header, and lets the server know the user's preferred language(s).
You will need to create a customer Filter (say MyFilter) and register it in web.xml.
public class MyFilter implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {
//
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
if(request.getParameter("language")==null) {
String userLocale = request.getHeader("Accept-Language");
Locale locale = request.getLocale();
String requestURI = request.getRequestURI();
// put your logic for userLocale and redirect accordingly
}
}
#Override
public void destroy() {
//
}
}
Register in web.xml
<filter>
<filter-name>localeFilter</filter-name>
<filter-class>com.my.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>localeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Update:
As suggested by #radimpe, the best practice will be using Persistent Cookie along with. This will help you, to trace, if some use wants to keep another language as default for your site
There are variety of ways in which you can do this :
I am assuming that user does not have to authenticate ?
Using Persistent Cookie for tracking the UPL - Disadvantages - when the user clears all the cookies manually - this preference is lost OR when the user is browsing in Private Mode then these cookies are not detected
IP Based - Assuming that there is no authentication for your website , you can do a predective Language detection by storing the IP and preference of the language. This again has the disadvantage - if the IP of the user changes
The combination of the two
The accept-language used alone , may be also a good criteria but then you would be binding the client to a specific language. It can be the starting point of determination

How to define default welcome page in an equinox OSGI server?

We are using OSGI Equinox "org.eclipse.equinox.http.registry.resources" extension to define resources accessible in our different JAR in our OSGI Equinox server. Most of them are just to point to static HTML content so there's no Servlet implementation. I was wondering what was the easiest way to define the default page for a sub folder (defining the "Welcome" file usually defined in a web.xml in standard Servlet packaging). Basically, I define a resource at /mynewresource and would link the user to be directed to index.html when he enters instead of getting a server error.
If you just want to have a default behavior of going to index.html on your resource, you can create that simple filter:
public class WelcomFilter implements javax.servlet.Filter {
/** {#inheritDoc} */
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/** {#inheritDoc} */
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
HttpServletRequest r = (HttpServletRequest) request;
if ("/".equals(r.getPathInfo())) {
r.getRequestDispatcher("index.html").forward(request, response);
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
}
/** {#inheritDoc} */
#Override
public void destroy() {
}
}
You have two choices: you can register this filter once at the root (/) but keep in mind that any request with no path info will get redirected to index.html or you can register it for the sub-domain where you want it. In any case, you need to use the equinox http filter extension.
<extension
point="org.eclipse.equinox.http.registry.filters">
<filter
alias="/mydomain"
class="com.abc.filters.WelcomeFilter">
</filter>
</extension>
There is no standardised way yet to define a default (or welcome) page in an OSGi server.
Coincidentally, I faced the same and decided to add this functionality to the Amdatu-Web project. Aside allowing non-Java resources to be served through the web, it now also allows you to define a default page like:
X-Web-Resource-Default-Page: index.html
or a default page for a specific directory:
X-Web-Resource-Default-Page: /path=index.html
The default page(s) will be served in case no file is requested.
It is not entirely done yet, as it needs some reviewing and I need to update the documentation and examples a bit on the Amdatu website. But, you can already take a look at the code (especially the demo project in the BitBucket project) to get an idea of how it should work.
Filters didn't work for me (using Kura/Equinox) however, using a custom HttpContext implementation I was able to add the required logic in getResources.

How do I specify a query string in Tomcat's <servlet-mapping> <url-pattern>?

I am running Tomcat 5.5.4 and have a servlet running with no problems. However, I'd like to set up a mapping to only launch the servlet when a URL containing a particular query string is submitted.
Right now in web.xml I have:
<servlet-mapping>
<servlet-name>MyServer</servlet-name>
<url-pattern>/go/*</url-pattern>
</servlet-mapping>
If a browser submits http://localhost/MyServer/go?P=123 the servlet is launched and all is well. However, I'd like to only launch that servlet if the URL is exactly as just shown. Unfortunately, right now if the URL is http://localhost/MyServer/go?P=AnyDarnThing the servlet still launches. I have tried setting up the following:
<url-pattern>/go?P=123</url-pattern>
but this results in The requested resource (/MyServer/go) is not available.
I've tried numerous variations (quoting the string, ...) on the above URL pattern but I always get the above error. I notice that if I (for debugging purposes) drop the "?" as in
<url-pattern>/goP=123</url-pattern>
I no longer get the error message and the server launches (but, of course, it doesn't respond to the "query string" because it's not properly formed.) This suggest to me that the "?" is causing a problem in the mapping. I've tried replacing it with its URL special character equivalent as follows:
<url-pattern>/go%3FP=123</url-pattern>
but this gives the same result just described above when I tried dropping the "?" altogether.
I realize I can let the servlet get launched when any query string is submitted and then "ignore" the request for all but the one I care about but there is a reason I'd prefer to not have the servlet launched to begin with. So, my question is, how can I configure the servlet so that it is only launched when a specific query string is included?
Thank you.
You can't do that. The url-pattern is pretty limited.
If you want to have distinct actions taken based on a GET parameter, you can do that manually. In the doGet() method of the servlet have a simple if-clause and invoke different methods depending on the query string / get param.
You can't do that using URL patterns.
You can achive this using filters. Implement a filter which will forward to the Servlet only if the query params exists.
Here is the how the filter will look like:
public class ServletAcessFilter implements Filter
{
public void init(FilterConfig filterConfig) throws ServletException
{
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException
{
//validate the request, check if the request can be forwarded to servlet.
if(request.getParameter("P").equalsIgnoreCase("123")){
filterChain.doFilter(request, response);
} else {
//write what you want to do if the request has no access
//below code will write 404 not found, you can do based on your requirement
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setStatus(404);
}
}
public void destroy()
{
}
}
Define the filter in the web.xml like this:
<filter>
<filter-name>ServletAccessFilter</filter-name>
<filter-class>com.ServletAcessFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ServletAccessFilter</filter-name>
<url-pattern>/go/*</url-pattern>
</filter-mapping>
To add to Bozho response, you may also try to move to Clean URLs
This will greatly increase your options in terms of URL pattern matching, and, in particular, may significantly ease configuration of a fronting reverse proxy if you ever need one.

Is it possible for a servlet filter to work out which servlet will handle the request

I'm writing a filter that performs logging and I need to disable this logging if the request is going to end up at a certain servlet.
Is there any way for the filter to know which servlet will handle the request?
You might want to setup servlet filter mapping to not fire it in case of requests for particular servlet altogether.
Example configuration could look like this assuming that there is one DefaultServlet that should not be impacted by filter and two other servlets FirstServlet and SecondServlet which have to be affected.
<filter-mapping>
<filter-name>MyFilter</filter-name>
<servlet-name>FirstServlet</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<servlet-name>SecondServlet</servlet-name>
</filter-mapping>
You can assign url pattern which are to be filtered
e.g.
<filter>
<filter-name>Admin</filter-name>
<filter-class>com.nil.FilterDemo.AdminFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Admin</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
This filter will run for every single request handled by the servlet engine with /admin mapping.
I always think that you should be able to make exceptions to url-patterns in a web.xml e.g. if you could do something like this:
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>
<match>/resources/*</match>
<except>/resouces/images/blah.jpg</except>
</url-pattern>
but you can't so that's no help to you!
You obviously have access to the URL in the Filter through the request object so you could do something like this:
public void doFilter(ServletRequest sRequest, ServletResponse sResponse,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)sRequest;
if(!request.getRequestURI.equals("/resources/images/blah.jpg")) {
doLogging();
}
chain.doFilter();
}
(hard-coded here but you'd probably read it from a property file) although this may not be of use to you as you mentioned servlets in your query as opposed to URL patterns.
EDIT: another thought. If you don't mind doing your logging after the servlet has completed you could do something like this:
public void doFilter(ServletRequest sRequest, ServletResponse sResponse,
FilterChain chain) throws IOException, ServletException {
sRequest.setAttribute("DO_LOGGING", new Boolean(true));
chain.doFilter();
Boolean doLogging = (Boolean)sRequest.getAttribute("DO_LOGGING");
if(doLogging) {
doLogging();
}
}
and your servlet that you want to exclude from logging can just set that attribute to false.
public void doGet(HttpServletRequest req,
HttpServletResponse res) throws IOException {
req.setAttribute("DO_LOGGING", new Boolean(false));
// other stuff
}

Categories

Resources