Monday, December 20, 2010

Grails 1.3.6, code-coverage and NTLM authentication error

Hi folks!

Edit on April 25th, 2011

Mike was kind enough to apply a hotfix that I made to the code-coverage plugin. This hotfix disables loading of external DTDs while processing cobertura.xml file. To that end if you're using this one and facing the issue described below you'll want to upgrade the plugin to version 1.2.3.

It's been a bad, bad day today, let me tell you. I'm still pissed off... but let's start from the beginning.

At first it's been great because the new Grails came out. New means better (and in fact it is better), new features - the usual stuff. Right up until you're forced to work behind an NTLM-protected proxy.

Well, first of all I'd like to point out that giving access to the Internet only via proxy is just asking for trouble. There's tons of apps simply not working from behind a proxy, especially one that needs authentication. Just take all Java applications working on Linux with nothing but the core runtime library and you'll know what I mean.

However up until the previous (1.3.5) version of Grails this problem has been overcomed by using Ivy that registered an NTLM authentication provider and all was just nice and dandy.

But in this version guys have upgraded to version 2.2 of Ivy which turned this feature off until Ivy is really in need to download something from the net. This means that if there's anything counting on proxy being setup correctly you're going to find yourself in deep sh..t.

There are 2 methods to overcome this problem:

1. Downgrade to Grails 1.3.5 (I'd recommend that unless like me you really need some of the new features that came to be in 1.3.6 like the "run-script" thingy - extra handy!!!)
2. Install a proxy server that can communicate with an up-stream NTLM-protected proxy

If you're counting on some bad-ass sites telling you to set the http.proxyUser and http.proxyPassword system settings to get it to work again please be adviced that it's just plain not true. This had been so ages ago, but now things are a lot more complicated and this mechanism ain't working anymore. Period.

Just remember: if you'll see something like this:
java.io.IOException: Server returned HTTP response code: 407 for URL: http://cobertura.sourceforge.net/xml/coverage-04.dtd
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:677)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1315)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startDTDEntity(XMLEntityManager.java:1282)
at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.setInputSource(XMLDTDScannerImpl.java:283)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(XMLDocumentScannerImpl.java:1194)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(XMLDocumentScannerImpl.java:1090)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:1003)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at _Events.replaceClosureNamesInXmlReports(_Events.groovy:118)
at _Events$replaceClosureNamesInXmlReports.callCurrent(Unknown Source)
at _Events.replaceClosureNamesInReports(_Events.groovy:89)
at _Events$_run_closure2.doCall(_Events.groovy:42)
at _GrailsEvents_groovy$_run_closure5.doCall(_GrailsEvents_groovy:58)
at _GrailsEvents_groovy$_run_closure5.call(_GrailsEvents_groovy)
at _GrailsTest_groovy$_run_closure1.doCall(_GrailsTest_groovy:203)
at TestApp$_run_closure1.doCall(TestApp.groovy:82)
at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:427)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:415)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.executeTargets(Gant.groovy:590)
at gant.Gant.executeTargets(Gant.groovy:589)

you're having issues with authorization (it's the 407 part of this call stack)

I hope this will help save someone tons of time that I spent to figure this damn thing out.

Oh! And if it'd not be enough it works just fine on Windows when you're logged in to the domain. Go figure!

2 comments:

Joseph Faisal Nusairat said...

Hey i saw your post, having the exact same problem

I hate both solutions you have let me tell ya was curious if you knew if 1.3.7 worked any better?

Matthias Hryniszak said...

Joseph: upgrade code-coverage plugin to 1.2.3.
See http://jira.grails.org/browse/GPCODECOVERAGE-35 for more details