New Widgetset Compilation Issue

Hi all,

I’m doing the implementation part of my Thesis using Vaadin on a Tomcat 7 with eclipse Luna and Vaadin 7.4.2.
I’m using external addons in my project and SOMETIMES, after a full widgetset compile I get the following error when I run the App through a browser:

NFO: Requested resource [/VAADIN/widgetsets/kn.widgetset.ThesisappWidgetset/807A8E6FB2CCC5E2AE2CD5059CA029C7.cache.js] not found from filesystem or through class loader. Add widgetset and/or theme JAR to your classpath or add files to WebContent/VAADIN folder. It’s rather frustrating because, as I’ve seen, the js file that the errors states, is the PREVIOUS (before the new Widgeset Compilation) .cache.js file that says it’s missing.

So I’ve cleared everything from the browser but still the same. I’ve tried to access the app through other browsers too, but without any luck.

I’ve also seen in the widgeset folder the new .js files and they are there. So somehow the link between the corresponding files doesn’t get updated.

Restart, clean etc all have been done, without any change.

Any thoughts?

I have been getting this for awhile as well. I had to go so far as creating a Filter that would send a Redirect to the newest cache.js. This is definitely a hack but it has worked for the most part. Currently having trouble when using an apache proxy with tomcat.

Happy to see I’m not the only person to have had this problem

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain filterChain) throws IOException, ServletException {
        String requestURI = ((HttpServletRequest) request).getRequestURI();
        if (requestURI.contains(".cache.js") && !requestURI.contains(jsString)) {
            ((HttpServletResponse) response).setContentType("application/javascript");
            if(requestURI.contains("deferredjs")){
                String toReplace = requestURI.substring(requestURI.indexOf("deferredjs/")+11, requestURI.lastIndexOf("/"));
                String newURI = requestURI.replace(toReplace, jsString);
                ((HttpServletResponse) response).sendRedirect(newURI);
            }else{
                String toReplace = requestURI.substring(requestURI.indexOf(widgetsetName+"/")+widgetsetName.size(), requestURI.lastIndexOf(".cache.js"));
                String newURI = requestURI.replace(toReplace, jsString);
                ((HttpServletResponse) response).sendRedirect(newURI);
            }
        }else{
            filterChain.doFilter(request, response);
        }
    }

Wick, you have solved a problem I have had for months. My variant of your solution is not optimum, including the need to manually specify the new widgetset prefix, but it works. I’ve tweaked the code a bit where I needed to make it work for me - for example to limit its applicability to the mobile widgetset. For less than fully competent programmers (like me) I include complete details of how I implemented this in case it helps someone else. Improvements and suggestions are welcome, especially if someone has an elegant way of automatically retrieving the new widgetset prefix. Various references in my file would have to be changed of course in another implementation…

[code]
package ca.demy.commonservlets;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*

  • This is a workaround for a bad behaviour between iOS and TouchKitServlet.
  • The concept of a servlet filter is explained here: http://tutorials.jenkov.com/java-servlets/servlet-filters.html
  • The idea behind this filter was seeded from this thread: https://vaadin.com/forum#!/thread/9940804/9957413
  • There is an entry in web.xml which intercepts any request for a url that ends in .js and sends it here
  • We’re looking for any reference to a mobile widgetset javascript file. It would have this form and be the result
  • of a mobile widgetset compilation: F105D1FA987853D3D4A74D66FBC9A59C.cache.js
  • The problem being solved by this class is that an iOS device using Home Screen seeks the previous
  • version of the widgetset as it refers to its cached version instead of requesting whatever the
  • server’s got. Other phones and desktop machines don’t seem to have that problem.
  • So this filter initially looks for 3 conditions
    1. That the request is for a mobile as opposed to the main widgetset
    1. That the request contains a reference to a [xxx]
      .cache.js file
    1. That the request is for an out of date file
  • Then the doFilter substitutes requests for the old .cache.js file with the new one
  • either in the deferredjs folder or in reference tot he [xxx]
    .cache.js file

*/

public class OldWidgetsetRedirect implements Filter {

// define the mobile widgetset as it would appear in a request from a phone
String widgetsetName     = "/VAADIN/widgetsets/ca.demy.widgetset.FossMobileWidgetset/";

// TODO find a way to read this automatically rather than having to write it here after a 
// widgetset compile
// define the current latest prefix set by a widgetset compile on cache.js files
// this currently needs to be manually changed after every widgetset compile
String jsString            = "F105D1FA987853D3D4A74D66FBC9A59C";

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    // nothing here
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
    // the URI requested by the phone
    String requestURI = ((HttpServletRequest) request).getRequestURI();

    // if the request is referring to the mobile widgetset, is for the file type of interest and is not referring to the correct/current one...

    if (requestURI.contains(widgetsetName) && requestURI.contains(".cache.js") && !requestURI.contains(jsString)) {
        ((HttpServletResponse) response).setContentType("application/javascript");

        // replace requests for old files in the deferredjs folder with references to the new one
        if (requestURI.contains("deferredjs")){
            String toReplace = requestURI.substring(requestURI.indexOf("deferredjs/")+11, requestURI.lastIndexOf("/"));
            String newURI = requestURI.replace(toReplace, jsString);
            ((HttpServletResponse) response).sendRedirect(newURI);
            
        // replace requests for the old [xxx]

.cache.js with a reference to the current one
} else {
String toReplace = requestURI.substring(requestURI.indexOf(widgetsetName)+widgetsetName.length(), requestURI.lastIndexOf(“.cache.js”));
String newURI = requestURI.replace(toReplace, jsString);
((HttpServletResponse) response).sendRedirect(newURI);
}
} else {
filterChain.doFilter(request, response);
}
}

@Override
public void destroy() {
    // nothing here        
}

}
[/code]And in web.xml (I use servlet 3.1 and annotations, but I guess this kind of thing needs a web.xml file… (?) )

<filter>
    <filter-name>oldWidgetsetWorkaroundFilter</filter-name>
    <filter-class>ca.demy.commonservlets.OldWidgetsetRedirect</filter-class>
/filter>

<filter-mapping>
    <filter-name>oldWidgetsetWorkaroundFilter</filter-name>
    <url-pattern>*.js</url-pattern>
</filter-mapping>

Thanks a lot guys! Much appreciated!