Wednesday, August 30, 2006

Drupal idiosyncracies

  • The always present "Create Content" menu item (even when users aren't logged in)
http://drupal.org/node/47212
In particular, simply "Reset" the menu item should fix it

  • Read More tag in postings
    http://drupal.org/node/64051
Menus
Should write module to allow new terms to be added to menu system. At moment must create terms. Then create content using those terms. As part of this you can select create menu item.

Nice Menus.
By default css only supplies styles for 1 sublevel. Thus higher sublevels autoexpand. Add the following to stop this
(see http://drupal.org/node/65482)

// Add extra layer to stop 2nd level submenus from autoexpanding
//level 2
ul.nice-menu ul,
ul.nice-menu li:hover ul ul, ul.nice-menu li.over ul ul,
ul.nice-menu li:hover li:hover ul ul, ul.nice-menu li.over li.over ul ul {
display:none;
}

ul.nice-menu li:hover ul, ul.nice-menu li.over ul,
ul.nice-menu li:hover li:hover ul, ul.nice-menu li.over li.over ul,
ul.nice-menu li:hover li:hover li:hover ul, ul.nice-menu li.over li.over li.over ul {
display:block;
}

//Level 3
ul.nice-menu ul,
ul.nice-menu li:hover ul ul, ul.nice-menu li.over ul ul,
ul.nice-menu li:hover li:hover ul ul, ul.nice-menu li.over li.over ul ul,
ul.nice-menu li:hover li:hover li:hover ul ul, ul.nice-menu li.over li.over li.over ul ul {
display:none;
}

ul.nice-menu li:hover ul, ul.nice-menu li.over ul,
ul.nice-menu li:hover li:hover ul, ul.nice-menu li.over li.over ul,
ul.nice-menu li:hover li:hover li:hover ul, ul.nice-menu li.over li.over li.over ul,
ul.nice-menu li:hover li:hover li:hover li:hover ul, ul.nice-menu li.over li.over li.over li.over ul {
display:block;

Wednesday, August 16, 2006

Java Spring and Locales

Related to my previous post. We were updating a web app and localizing it for some new countries.

The jsps used some Spring tag libs.

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" />


Spring comes with an inbuilt LocaleResolver. By default it uses the AcceptHeaderLocaleResolver which detects the clients Locale from the Http headers (which are sent with the bowsers request).

In our case we didn't want the client locale to get picket up. We wanted to set it based on the servername. (To do these we added some virtual hosts to our tomcat instance).

Then to update the Spring Locale we had to use the SessionLocaleResolver . This has to be instantiated via the Spring xml file (otherwise it will default to AceptHeaderLocaleResolver).



We then simply set the Locale froma filter.

String servername = httpRequest.getServerName();
Locale locale = null;
if(servername.indexOf(".co.uk")>0){
_log.info("Setting UK locale");
locale = Locale.UK;
}else if(servername.indexOf(".fr")>0){
_log.info("Setting FR locale");
locale = Locale.FRANCE;
}else if(servername.indexOf(".de")>0){
_log.info("Setting DE locale");
locale = Locale.GERMANY;
}else{
_log.info("Cannot ascertain originating server. Defaulting to UK locale");
locale = Locale.UK;
}


HttpServletRequest

I keep forgetting these value. So I'm writing it down here to remember

Within a servlet, or Filter (or jsp) you can access the following information about the request.

httpRequest.getContextPath(); // =/webapp
httpRequest.getRequestURI(); // =/webapp/webhome
httpRequest.getServletPath(); // = /webhome
httpRequest.getRequestURL(); // = http://mybox.my:11600/webapp/webhome?q=query&r=prevPage
httpRequest.getRequestURI(); // = http://mybox.my:11600/webapp/webhome

httpRequest.getServerName(); // = mybox.my (1)
httpRequest.getRemoteHost(); // = 10.149.93.49 (2)
httpRequest.getRemoteAddr(); // = 10.149.93.49
httpRequest.getRemoteUser(); // = null ... (3)

N.B.
If you perform a RequestDispatcher.forward() then all the above methods will reflect the new forwarded values. Personally I didn't think the javadocs made this clear.

As of Servlet spec 2.4 however you can still access the original client request data using the following attributes. (see http://www.javaworld.com/javaworld/jw-03-2003/jw-0328-servlet_p.html)

  • javax.servlet.forward.request_uri
  • javax.servlet.forward.context_path
  • javax.servlet.forward.servlet_path
  • javax.servlet.forward.path_info
  • javax.servlet.forward.query_string

Inside a forwarded servlet you'll see getRequestURI() return the path to the target servlet as always, but now if you want the original path, you can call request.getAttribute("javax.servlet.forward.request_uri"). One special caveat: if forward() happens through a getNamedDispatcher() call, these attributes aren't set because, in that case, the original path elements aren't changed.

Note from servlet spec 2.2 there already exists

  • javax.servlet.include.request_uri
  • javax.servlet.include.context_path
  • javax.servlet.include.servlet_path
  • javax.servlet.include.path_info
  • javax.servlet.include.query_string
However, these work just the opposite of the forward() attributes. In an include(), the path elements don't change, so the include attributes act as the backdoor to access the target servlet's path elements. Compare this with a forward() where the path elements change so the forward attributes represent the backdoor to the original path elements.

Should filters invoke for forwarded requests? Included requests? What about for URIs invoked via the mechanism? Before Servlet 2.4, these questions were left as open issues. Now Servlet 2.4 makes it a developer's choice. There's a new element in the deployment descriptor with possible values REQUEST, FORWARD, INCLUDE, and ERROR. You can add any number of entries to a like this:


<filter-mapping>
<filter-name>Logging Filter</filter-name>
<url-pattern>/products/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>

This indicates the filter should be applied to requests directly from the client as well as forward requests. Adding the INCLUDE and ERROR values also indicates that the filter should additionally be applied for include requests and requests. Mix and match for what you want. If you don't specify any elements, the default is REQUEST.

The last RequestDispatcher change is to allow, for the first time, relative paths in request.getRequestDispatcher() calls. The path will be interpreted relative to the current request's path. It's a minor change, but comes in handy when dispatching to a sibling servlet.




Notes:
No all these method are available on the basic ServletRequest. Normally I just cast the basic ServletRequest into a HttpServletRequest, since I am normally only writting web apps.

1/ This is the server name from the Request. You can set up your web server to be multi hosted using virtual hosts. (Heres an example for tomcat). Then you can use this variable to differentiate on which host they came in on. We are using this for setting the locale on one project. (In general it is better to choose the locale based on the request,but we have specific reasons for doing it this way).

2/ This is the clients IP address. Can be used for logging.

3/I'm guess this will show a value if the page is protected by HttpAuthentication.

For Php equivilents check out this page

http://www.php.net/reserved.variables