Hi Doug,
Disclosure : I haven’t tried this…
There is nothing magic about themes and CSS in Vaadin; by call Application#setTheme(themeName), the HTML document in the browser is modified to include a css link to the webapp e.g.
setTheme(“example-theme”)
As a far as I can see, there is nothing to stop you creating and mapping your own servlet to serve up the CSS - which could then be dynamically generated from the database. I think that this the way I would tackle this problem :
After user login, call Application#setTheme(“mygreatapp-” + userName);
Create a servlet filter to capture all requests to VAADIN/themes before it hits the VAADIN servlet, and snaffle any specifically for your “mygreatapp-*” theme, and forward it to your own servlet where you generate the css (probably with an import to get the standard non-dynamic css)
The example code below will almost certainly not work out of the box - I’ve not compiled it, let alone actually tested it. However, it illustrates my intent clearer than stilted prose. Well, IMHO.
Hope that helps,
Cheers,
Charles.
web.xml
<filter>
<filter-name>theme-filter</filter-name>
<filter-class>org.example.ThemeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>org.example.ThemeFilter</filter-name>
<url-pattern>/VAADIN/themes/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>generate-stylesheet</servlet-name>
<servlet-class>org.example.GenerateStylesheetServlet</servlet-class>
</servlet>
ThemeFilter : captures requests for myapp-* theme, and redirects them to the GenerateStylesheetServlet
public class ThemeFilter implements Filter {
private Pattern regex;
private FilterConfig config;
public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
/* Note : This regex probably won't work first time - my regex foo is minimal without lots of try-it-and-fix-it loops */
regex = Pattern.compile("VAADIN/themes/mygreatapp-(.*)/styles.css");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String uri = httpRequest.getRequestURI();
Matcher matcher = regex.matcher(uri);
if(matcher.find()){
/* It's a user-specific CSS request : extraxt the user name, stick it in the request attributes, and forward
to a named servlet */
String userName = matcher.group(1);
ServletContext context = config.getServletContext();
RequestDispatcher dispatcher = context.getNamedDispatcher("generate-stylesheet");
request.setAttribute("username", userName);
dispatcher.forward(request, response);
} else {
/* No match : Pass it through to the standard mechanism */
filterChain.doFilter(request,response);
}
}
public void destroy() {
//NOP
}
[b]
GenerateStyleSheetServlet : Actually serves up the customized CSS[b]
/**
* This servlet generates a CSS style sheet for the given user (from the request attribute "username").
* Note that I have added an import for "reindeer" theme to inherit most of the CSS from.
*/
public class GenerateStylesheetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName = (String) request.getAttribute("username");
String additionalCSS = getCSSForUser("username");
response.setContentType("text/css");
PrintWriter out = response.getWriter();
out.println("/* Dynamically generated for user " + userName + " at " + new Date().toString() + " */");
out.println("@import \"../reindeer/styles.css\"");
out.println(additionalCSS);
out.close();
}
private String getCSSForUser(String s) {
// TODO Your DB Stuff Here
return "";
}
}