Monday, March 17, 2008

IE6 problem with Dojo: Could not load 'dojo.parser'

I encountered this problem when testing with IE 6:

Error: Could not load 'dojo.parser'; last tried './parser.js'

After researching it a bit, it usually occurs as the result of a script that loads before the dojo stuff and which does a document.write. Apparently this confuses dojo. The solution is to use the baseUrl property of djConfig to manually specify the base path (the path to the dojo.js file):
      <script type="text/javascript" src="../dojo_tools/dojo/dojo.js"
djConfig="parseOnLoad: true, baseUrl: '/dojo_tools/dojo/'"></script>

Note the baseUrl should have a trailing '/'.

When dojo loads, if no baseUrl is provided, dojo will try to dynamically determine the base url. However, other scripts can interfere with this (at least on IE), so manually specifying it fixes it.

Thursday, February 28, 2008

Dojo xhr to update a div

Using ajax to update a portlet quickly becomes a requirement when you get a bunch of portlets on a page and reloading everything is slow. So in setting out to use dojo to do this, I figured it required nothing more than setting the innerHTML of my div with the new content. It's not that simple, however, if the panel contains dojo's "dijit" widgets (in this case, I had a dijit.layout.TabContainer returned with the ajax content). BTW, dojo folks, the TabContainer worked flawlessly right out of the box and was clean and simple--nice job. In comparing the before/after, it was apparent that when the div content was rendered when the entire page loaded, dojo/dijit was wiring up the tab elements with all the required events and attributes. However, when the ajax content was set as innerHTML, this wasn't happening. It was a bit tough to figure out mostly because I wasn't sure what to google on to find the solution. I tried a few things, including making the div for the content a dijit.layout.ContentPane--but that's just part of what's needed. Here's what the content pane div looks like:
<div id="ajaxReportBody" dojoType="dijit.layout.ContentPane">
<c:import url="reportBody.jsp" />
</div>

The other piece is to make sure you use setContent() in your xhr load function on the dijit widget (in this case, the content pane div), instead of innerHMTL:
dojo.xhrPost( { 
...
load: function(response, ioArgs) {
...
dijit.byId("ajaxReportBody").setContent(response); // KEY!
return response;
},
...

When you use setContent(), dijit will redo the plumbing in the new content for you. Also note that you must use digit.byId(), not dojo.byId().

Some references indicated that you need an executeScripts="true" on the content pane div. However, this is no longer true AFAICT (I'm using dojo 1.0.2).

BTW, best reference I found on the subject was here.

Tuesday, January 8, 2008

Code formatting in Blogger

is a real PITA. Here's an web page utility (uses javascript) that makes it easier:
Greg Houston's Formatter for blog code
Have a better solution? Post a comment.

Hacking an WSRP portlet request using Groovy

I wanted to invoke a portlet without having to run it through a portal. I have a portlet currently deployed in Oracle Portal and figured it would be "fun" to try invoking it using Groovy--I didn't see any slam-dunk toolkits for this (I didn't look too hard). WSRP uses Soap, so the first step was firing up Wireshark to sniff a real request (sanitized to protect the innocent):

POST /MyPortlet/portlets/WSRPBaseService HTTP/1.1
Host: mycomputer:8080
Connection: keep-alive, TE
TE: trailers, deflate, gzip, compress
User-Agent: RPT-HTTPClient/0.3-3
Oracle-ECID: 86139989405,1
Cookie: JSESSIONID=80f4383422b8fbea0c8532804298a55ba92d09dfb9a6
SOAPAction: "urn:oasis:names:tc:wsrp:v1:getMarkup"
Accept-Encoding: gzip, x-gzip, compress, x-compress
Content-type: text/xml; charset="utf-8"
Content-length: 2165

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="urn:oasis:names:tc:wsrp:v1:types"><env:Body><ns0:getMarkup><ns0:registrationContext><ns0:registrationHandle>C:xxx.xx.xx.xx:-5fd1fa94:11740915845:-7ffe</ns0:registrationHandle></ns0:registrationContext><ns0:portletContext><ns0:portletHandle>E:0:xxx.xx.xx.xx:-5fd1fa94:11740915845:-7ffd</ns0:portletHandle></ns0:portletContext><ns0:runtimeContext><ns0:userAuthentication>wsrp:xxxxxxxx</ns0:userAuthentication><ns0:portletInstanceKey>1179_354032_1179_1_1</ns0:portletInstanceKey><ns0:namespacePrefix>__ns1179_354032_1179_1_1_</ns0:namespacePrefix></ns0:runtimeContext><ns0:userContext><ns0:userContextKey>mylogin</ns0:userContextKey></ns0:userContext><ns0:markupParams><ns0:secureClientCommunication>false</ns0:secureClientCommunication><ns0:locales>en-us</ns0:locales><ns0:mimeTypes>text/html</ns0:mimeTypes><ns0:mode>wsrp:view</ns0:mode><ns0:windowState>wsrp:normal</ns0:windowState><ns0:clientData><ns0:userAgent>Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727) RPT-HTTPClient/0.3-3</ns0:userAgent><ns0:extensions><oracle:GenericExtension xmlns:oracle="http://xmlns.oracle.com/portal/wsrp/v1"><ns0:NamedString name="X-Oracle-Device.MaxDocSize"><ns0:value>0</ns0:value></ns0:NamedString><ns0:NamedString name="X-Oracle-Device.Class"><ns0:value>pcbrowser</ns0:value></ns0:NamedString><ns0:NamedString name="X-Oracle-Device.Secure"><ns0:value>false</ns0:value></ns0:NamedString><ns0:NamedString name="X-Oracle-Device.Orientation"><ns0:value>landscape</ns0:value></ns0:NamedString></oracle:GenericExtension></ns0:extensions></ns0:clientData><ns0:markupCharacterSets>utf-8</ns0:markupCharacterSets><ns0:validNewModes>wsrp:view</ns0:validNewModes><ns0:validNewWindowStates>wsrp:normal</ns0:validNewWindowStates><ns0:validNewWindowStates>wsrp:maximized</ns0:validNewWindowStates><ns0:validNewWindowStates>wsrp:minimized</ns0:validNewWindowStates></ns0:markupParams></ns0:getMarkup></env:Body></env:Envelope>



It would probably take a bit of trial and error to hack that for another portal/portlet, but who knows.

Putting this in groovy (stripping out the JSESSIONID):

def headerLines = """\
Host: mycomputer:8080
Connection: keep-alive, TE
TE: trailers, deflate, gzip, compress
User-Agent: RPT-HTTPClient/0.3-3
Oracle-ECID: 86139989405,1
SOAPAction: "urn:oasis:names:tc:wsrp:v1:getMarkup"
Accept-Encoding: gzip, x-gzip, compress, x-compress
Content-type: text/xml; charset="utf-8"
Content-length: 2165
"""

def postBody = """\
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="urn:oasis:names:tc:wsrp:v1:types"><env:Body><ns0:getMarkup><ns0:registrationContext><ns0:registrationHandle>C:xxx.xx.xx.xx:-5fd1fa94:11740915845:-7ffe</ns0:registrationHandle></ns0:registrationContext><ns0:portletContext><ns0:portletHandle>E:0:xxx.xx.xx.xx:-5fd1fa94:11740915845:-7ffd</ns0:portletHandle></ns0:portletContext><ns0:runtimeContext><ns0:userAuthentication>wsrp:xxxxxxxx</ns0:userAuthentication><ns0:portletInstanceKey>1179_354032_1179_1_1</ns0:portletInstanceKey><ns0:namespacePrefix>__ns1179_354032_1179_1_1_</ns0:namespacePrefix></ns0:runtimeContext><ns0:userContext><ns0:userContextKey>mylogin</ns0:userContextKey></ns0:userContext><ns0:markupParams><ns0:secureClientCommunication>false</ns0:secureClientCommunication><ns0:locales>en-us</ns0:locales><ns0:mimeTypes>text/html</ns0:mimeTypes><ns0:mode>wsrp:view</ns0:mode><ns0:windowState>wsrp:normal</ns0:windowState><ns0:clientData><ns0:userAgent>Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727) RPT-HTTPClient/0.3-3</ns0:userAgent><ns0:extensions><oracle:GenericExtension xmlns:oracle="http://xmlns.oracle.com/portal/wsrp/v1"><ns0:NamedString name="X-Oracle-Device.MaxDocSize"><ns0:value>0</ns0:value></ns0:NamedString><ns0:NamedString name="X-Oracle-Device.Class"><ns0:value>pcbrowser</ns0:value></ns0:NamedString><ns0:NamedString name="X-Oracle-Device.Secure"><ns0:value>false</ns0:value></ns0:NamedString><ns0:NamedString name="X-Oracle-Device.Orientation"><ns0:value>landscape</ns0:value></ns0:NamedString></oracle:GenericExtension></ns0:extensions></ns0:clientData><ns0:markupCharacterSets>utf-8</ns0:markupCharacterSets><ns0:validNewModes>wsrp:view</ns0:validNewModes><ns0:validNewWindowStates>wsrp:normal</ns0:validNewWindowStates><ns0:validNewWindowStates>wsrp:maximized</ns0:validNewWindowStates><ns0:validNewWindowStates>wsrp:minimized</ns0:validNewWindowStates></ns0:markupParams></ns0:getMarkup></env:Body></env:Envelope>"""

def url = new URL("http://mycomputer:8080/MyPortlet/portlets/WSRPBaseService")
def conn = url.openConnection()
conn.doOutput = true

headerArray = headerLines.split("\n")
headerArray.each {
iColon = it.indexOf(":")
name = it[0..<iColon]
value = it[iColon+1..-1].trim()
println """Header $name = $value"""
conn.setRequestProperty(name, value)
}

conn.outputStream << postBody
conn.inputStream.eachLine { println it }


Running this produces the following output:

&lt;p class="portlet-font"&gt;Welcome, this is the view mode.&lt;/p&gt;
Current Date/Time is: 2008-01-08 12:20:36.0</ns0:markupString><ns0:locale>en</ns0:locale><ns0:requiresUrlRewriting>false</ns0:requiresUrlRewriting><ns0:cacheControl><ns0:expires>0</ns0:expires><ns0:userScope>wsrp:perUser</ns0:userScope></ns0:cacheControl><ns0:preferredTitle>ComboPortlet</ns0:preferredTitle></ns0:markupContext></ns0:getMarkupResponse></env:Body></env:Envelope>



If you have suggestions for a good library for this, or improvements to the groovy code, please comment.