[CommandBox 5.3.1] Concurrent Modification Exception in ACF

I’ve been experimenting with customizing error pages in my server.json file in Commandbox/Undertow. In the documentation here, it includes some code you can execute to view a list of error variables:

req = getPageContext().getRequest();
names = req.getAttributeNames();
while( names.hasMoreElements() ) {
    name = names.nextElement();
    writeDump( name & ' = ' & req.getAttribute( name ) );
}

If I run this page in ACF versions 2018, 2018, or 2021 I get the very first element which looks like this:
javax.servlet.forward.servlet_path = /my-page/
followed by a null exception (ConcurrentModificationException) error: https://i.imgur.com/3ZOT0oU.png

The stack trace is as follows: Stack Traceat cf_4042ecfm2093882108.runPage(D:/Dropbox/Repositories/ccis-web/_ - Pastebin.com

When I run the script on Lucee@5 it works as expected:

Interesting. FWIW, a ConcurrentModificationException is not a “null” exception. A concurrent hashmap is basically a non thread safe struct in java which doesn’t use synchronized methods so it’s faster but if two threads try to modify it at the same time, it will throw an error. I’m not clear why the simple code above would throw an error.

Haha, ok so I just went and tried this and figured it out. The trick is to NOT use writeDump() as ColdFusion apparently internally is screwing around with the enumeration object when you use the dump tag. If you change that code to be writeOutput() it works just fine:

req = getPageContext().getRequest();
names = req.getAttributeNames();

while( names.hasMoreElements() ) {
    name = names.nextElement();
    writeOutput( name & ' = ' & req.getAttribute( name ) & '<br>' );
}

Of course, if you know the name of the request attribute you want, you don’t even need to loop, you can just get it directly:

writeOutput( getPageContext()
  .getRequest()
  .getAttribute( 'javax.servlet.error.request_uri' ) );

For bonus fun, here’s some facts about the cgi scope. It gets some of its data from the ServletRequets’s Attributes, such as request URL and path info. There’s even a hidden trick where you can access any request HTTP header via the CGI scope (I found this one reading the Lucee source code):

cgi['http_User-Agent']

In Adobe ColdFusion, you can also access any Servlet Request Attribute via the CGI scope like so:

writeOutput( cgi['javax.servlet.error.request_uri'] );

which means you don’t really even need any of the other methods. Sadly, Lucee Server doesn’t support this, so I put in a ticket: [LDEV-3603] CGI doesn't work for any ServletRequest Attribute - Lucee

1 Like

Thanks, @bdw429s! Insightful and helpful information as always. :slight_smile:

I just updated the CommandBox docs as well:

https://commandbox.ortusbooks.com/embedded-server/configuring-your-server/custom-error-pages#accessing-error-variables

1 Like