Tuesday, September 08, 2009

Is Eclipse deleting XML resources from my build path?

Keywords:
eclipse 3.4.0 ganymede FileNotFoundException xml properties build classpath filtered resources deleted excluded "class path resource cannot be resolved"

Problem:
I have a project where configuration resources (mostly hibernate - hibernate.cfg.xml & *.hbm.xml) exist in the same folders as the java source and it's expected that these are copied to the build output so they can be loaded from the classpath.

It seems eclipse is "cleaning up" the XML files from the build output folder. Check the include/exclude settings on the project and Included is set to (All). Adding *.xml explicitly to the included list makes no difference.

Out of curiosity, manually copying an XML file to the build output folder and refreshing the project causes the XML to be deleted. Why?

Solution:
I'm not sure if it was an update or plugin that caused this, but the problem is with the Filtered Resources setting.

In Window -> Preferences:
go to: Java > Compiler > Building
in Output folder section:
  • check the Filtered resources value
  • if *.xml is in the comma separated list, this is the cause.
    Remove from the list and allow the Project rebuild.

As mentioned, even if you explicitly add *.xml to be included in your Project settings the above global setting will cause it to be excluded.

Friday, June 19, 2009

JSTL formatNumber as percentage gets invalid attribute error

Keywords:
fmt:formatNumber <formatNumber> invalid type attribute: "percentage" percent

Problem:
The JSTL Tag Library documentation seems to indicate that to format a number as a percentage you'd use:

<fmt:formatNumber type="percentage" value="0.5"/>


This gives the error message
<formatNumber>, invalid type attribute: "percentage"

Solution:
Although the documentation for type says "Specifies whether the value is to be formatted as number, currency, or percentage" these aren't the possible values - it's "percent" for percentage:

<fmt:formatNumber type="percent" value="0.5"/>


Notes:
If you know a good reference for JSTL I'd like to know ...

The Appendix A from JSTL in Action is not bad - it documents possible values for formatNumber type at least.

Tuesday, June 16, 2009

Eclipse build errors - java.lang.object cannot be resolved

Keywords:
eclipse 3.4.0 ganymede The type java.lang.object "cannot be resolved" "Cannot find the class file" "refers to the missing type"

Problem:
Opened eclipse, it needed to do a full workspace build (probably because ant scripts have updated class files and it needs to refresh). Random classes in the project now no longer compile. Examples of the errors being reported:



DescriptionResourcePathLocationType
The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class filesMyClass.javaMyProject/src/com/exampleline 1Java Problem
The project was not built since its build path is incomplete. Cannot find the class file for java.lang.Object. Fix the build path then try building this projectMyProjectUnknownJava Problem
The method myMethod(SomeClass) from the type MyOtherClass refers to the missing type (insert java type here: InputStream|File|Vector|IOException|etc)MyOtherClass.javaMyProject/src/com/exampleline 123Java Problem


Solution:
It sounds like this has been a known issue (Bug 67414)that was resolved in 3.0 ... someone has commented that it's occurring for them in 3.4 as well.

In the mean time, the work around is to remove the JRE System Library from the project and then add it back again.
Here are the steps:
  1. Go to properties of project with the build error (right click > Properties)
  2. View the "Libraries" tab in the "Build Path" section
  3. Find the "JRE System Library" in the list (if this is missing then this error message is not an eclipse bug but a mis-configured project)
  4. Remove the "JRE System Library"
  5. Hit "Add Library ...", Select "JRE System Library" and add the appropriate JRE for the project (eg. 'Workspace default JRE')
  6. Hit "Finish" in the library selection and "OK" in the project properties and then wait for the re-build of the project
  7. Hopefully the error will be resolved ...

Friday, May 08, 2009

Javascript history.back() not working for iframes in Firefox

Keywords:
javascript history frame iframe go(-1) back firefox 3 top self

Problem:
You can get a hyperlink to behave as a "back" with a bit of javascript:

<a href="javascript:history.back()">back</a>

or (saying go back one place in the history - equivalent to the above):

<a href="javascript:history.go(-1)">back</a>


This works fine in all browsers when the page is in the main-view. If this javascript is encountered in an iframe you expect that you get the previous page that was loaded in that iframe. In firefox 3+ you're taken back in the main view page not the iframe - a nuisance if there's a detailed browsing history in the iframe view. Why does it work fine in other browsers and previous versions of firefox?

Solution:
I don't know why, but it seems that in firefox 3+ when you say history this becomes implicitly top.history. Someone has tried to raise this with mozilla with not much luck - javascript:history.back() and Firefox 3.0.1 and iframes.

The solution is to be explicit about which frame you want to navigate back with. If you just want all browsers to behave the same then self refers to the frame the user is clicking in (therefore in other browsers history is implicitly self.history). So the go-back hyperlink becomes:

<a href="javascript:self.history.back()">back</a>

or:

<a href="javascript:self.history.go(-1)">back</a>


This will behave the same regardless of if the page is loaded in the main-view or in an frame/iframe.

Wednesday, April 08, 2009

IE8 Compatibility Issues and working around them for HTML, Java and GWT

Keywords:
IE8 compatibility X-UA-Compatible java filter http-equiv GWT "links not working" broken EmulateIE7 compliance

Problem:
You're either certain your website/webapp is broken in IE8 or suspect it might be. What can you do?

For browsers such as firefox and IE7, you used the DOCTYPE switch to indicate if it should treat your page as being in "standards" mode or "quirks" mode. As discussed on A List Apart "standards" is open to interpretation and even if the page didn't fully comply with the standard it referenced, it could expect the browser to have a reasonable crack at letting it work.

Not any more. IE8 renders all pages in standards mode by default and it's interpretation is as far as I can tell, stricter than any other browser. In this mode, many HTML, CSS and javascript/DOM elements (that were introduced by older versions IE! - and in some cases understood by other browsers such as firefox) are not just deprecated, they're completely not there - meaning any reference to them will in most cases stop the page/application working in the browser. When this happens, the page layout may be askew, links may stop working and miscellaneous javascript errors will be flagged in the status bar.

If you're not sure if your webpage/webapp is strictly standards compliant, it most probably isn't.

GWT is effected - see Dan Moore's post and GWT Issue #3329.

Solution:
IE8 users can make broken pages work again by opting-out of the "most strict" standards treatment on a site-by-site basis using the "Compatibility View" button but you can save them the trouble by using a new http-header tag X-UA-Compatible.

The A List Apart article above describes the merits of being able to target specific versions (and the comments seem to mostly disagree :) but in the majority of cases I imagine you just want the page to be treated the way IE7 did - "standards" mode (with "flexibility") for pages that require it and "quirks" mode for all others. So use the "IE=EmulateIE7" value by either:

  1. making the server side code add this http header to every response
    X-UA-Compatible: IE=EmulateIE7

  2. or add the following meta tag to the <head> element of the page (which is essentially the equivalent to setting values on the http response)
    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    


You can cover the entire java web application by defining a filter as documented by Mark McLaren:
    public void doFilter(ServletRequest request, 
                         ServletResponse response, 
                         FilterChain chain)
            throws IOException, ServletException {
        if (response instanceof HttpServletResponse) {
            ((HttpServletResponse) response).setHeader("X-UA-Compatible", "IE=EmulateIE7");
        }
        chain.doFilter(request, response);
    }


Apache hosted sites can be covered by using mod_headers. For example, assuming you have the module loaded, add the following to the httpd.conf file:
Header add X-UA-Compatible "IE=EmulateIE7" 



Notes:
Having trouble installing the release version of IE8? (for goodness sake, just get firefox :) But, if you really do want to get it working for yourself see Internet Explorer 8 is not supported on this operating system for a discussion of common issues.

Friday, February 13, 2009

XSLT output is missing the doctype

Keywords:
xslt identity transform missing doctype Document Type java DOM

Problem:
Running an XSLT 'identity transform' I would expect the XML data out to be identical to the data in ... it almost is, but it's missing the doctype declaration.
Can you tell the XSTL to keep the doctype in?

Solution:
Apparently not ... I can't find a good reference for this, but it seems that the spec (or at least xalan) is a bit vague on how this should be handled. Proposed work-arounds seem to be hard-coding the doctype in the <xsl:output> element (if outputting to xml) or hiding the doctype in the XSLT via <xsl:text disable-output-escaping="yes">.

If you want to make the inclusion of the doctype generic there's no pure XSTL solution - you can add it after the transform, but even that is not straightforward using pure java DOM elements ... here is the code:
    // assuming there's an inputDocument
    TransformerFactory factory = TransformerFactory.newInstance();
    StreamSource stylesheet = new StreamSource(stylesheetData);

    DOMSource source = new DOMSource(inputDocument);
    DOMResult result = new DOMResult();

    Transformer transformer = factory.newTransformer(stylesheet);
    transformer.transform(source, result);

    Document outputDocument = (Document)result.getNode();
    if (inputDocument.getDoctype() != null) {
        DocumentType inputDocType = inputDocument.getDoctype();
        
        // you can't importNode for DocumentType nodes but you can create 
        // them via DOMImplementation from there insert is easy
        DOMImplementation domImpl = outputDocument.getImplementation();
        DocumentType outputDocType = domImpl.createDocumentType(
              inputDocType.getName()
            , inputDocType.getPublicId()
            , inputDocType.getSystemId());
        outputDocument.insertBefore(outputDocType, outputDocument.getDocumentElement());
    } 


Notes:
It's interesting that this code is not allowed:
    DocumentType outputDocType = (DocumentType) outputDocument.importNode(inputDocType, true /*deep*/);

It seems DocumentType is a special element that can't be imported.

It's also interesting there's no method straight on the document:
    DocumentType outputDocType = outputDocument.createDocumentType(...);

The only way to get this kind of element is to obtain the special DOMImplementation object via the Document.getImplementation() method.

Quirks with the implementation? I've looked at this issue too long already to bother to find out why :)

Friday, January 16, 2009

GWT Button acts as a submit in WebKit browsers

Keywords:
HTML button element form WebKit Chrome Safari iPhone

Problem:
In WebKit browsers, the Button widget in a GWT application seems to always act as a submit, regardless of event sinking (via ClickListener) behaviour added to it.

In Firefox (and IE!) the button works fine - that is the 'onclick' behaviour added to the widget via the GWT listening architecture is executed and the page is not submitted.

Solution:
A clue to the solution is in the code for the GWT Button (thank goodness for source code - see Button.adjustType(Element button)).

It seems to be a work around for Firefox. The W3C spec states that the default value for button type is 'submit'. Firefox does this explicitly in the DOM and when detected, this is fixed by the GWT JSNI (JavaScript Native Interface) code.

It would seem that for WebKit browsers this default is enforced but not made explicit in the DOM so this GWT snippet does not get a chance to resolve the issue. The work around is to always be explicit about the button type (as recommended in W3Schoools).

You do this in GWT as follows:
     Button b = new Button("click here");
     DOM.setElementAttribute(b.getElement(), "type", "button");