The key [JAVAX] does not exist in the request scope

Hi All,

I’m attempting to port an OpenBD app over to Lucee, and I’ve hit a snag.

It’s a current CentOS 7 Minimal Install with Tomcat 8 and OpenJDK 8. I was successfully able to download the latest Lucee .war file, drop it in and get it up and running. I can pull up the initial landing page, log into both web/server admin pages, enable debugging, etc.

In attempting to run one of the scripts, there’s a line of code throwing an expression error.

<cfset results.folder = "#request.javax.servlet.error.request_uri#">

Error Message: _The key [JAVAX] does not exist in the request scope, only the following keys are available: [sqlregex]._

Top of JavaStackTrace

lucee.runtime.exp.ExpressionException: 
The key [JAVAX] does not exist in the request scope, 
only the following keys are available: [sqlregex].

at lucee.runtime.type.util.StructSupport.invalidKey(StructSupport.java:66)

Not having much luck finding any helpful info elsewhere. Thoughts? Hoping this is a simple context issue or something. Please let me know if any more details are needed.

Is that line of code that you posted something in your app’s code? I don’t recognize that as part of Lucee. What exactly is that line of code trying to do. I’m guessing there was some feature of OpenBD that would stick variables in the request scope or something that isn’t part of the AdobeCF/Lucee implementation. If you can tell us what part of your app is running that code and what information you’re trying to get, I’m sure we can help you get it. Right now, that error is simply that a key doesn’t exist in a struct, but that’s fairly meaningless without the context.

1 Like

Did you put a Struct with the key javax in the Request Scope? e.g.

Request.javax = { ... };

Because that’s what Lucee is looking for there and it doesn’t find anything at Request.javax

1 Like

It’s app code and I haven’t looked at in a few years. My comments are pretty vague.

Did a quick lookup on javax.servlet.error.request_uri which lead me to this page.

https://tomcat.apache.org/tomcat-8.0-doc/servletapi/constant-values.html

From this page, I found the row for ‘javax.servlet.error.request_uri’

https://tomcat.apache.org/tomcat-8.0-doc/servletapi/javax/servlet/RequestDispatcher.html#ERROR_REQUEST_URI

“The name of the request attribute that should be set by the container when custom error-handling servlet or JSP page is invoked. The value of the attribute is of type java.lang.String.”

That said, this particular script is a 404redirect script. When tomcat can’t find a resource, it’s supposed to grab some information from the requested URL, parse, and do some functions before exporting the 404 page to the user.

Right, but you can’t mix Servlet attributes with CFML Keys.

IIUC then you’re looking for CGI.SCRIPT_NAME or CGI.REQUEST_URL.

I’m almost certain openBD had a feature where it would promote variables sent in the http servlet response to the actual CFML request scope.

Try this code block (or something similar) to see if you can get at the variables:
https://ortus.gitbooks.io/commandbox-documentation/content/embedded_server/custom_error_pages.html#accessing-error-variables

That is a page in the CommandBox docs, but it’s the same thing-- it’s getting at the “request” variables set by the servlet container in your CFML code. Your servlet container has a concept of a “request” but your servlet knows nothing about CFML.

Also, please check up the page to see where the “request” variable is coming from. Adobe CF, for instance, will allow you to create variables named after scopes and actually overwrite the scope (which Lucee considers to be bad) It’s possible your code was declaring it’s own “request” variable and using it, but Lucee’s scope lookups are a bit different since we consider that “bad code”.

Thanks for the info.

I did a extended find on this in the app’s code. This is the only instance it’s used.

The bad code in in the 404 script is being called from a function declared in a .cfc

I did a quick test and made a test404error.cfm page, and declared it as the 404 error page in both Lucee and OpenBD’s respect web.xml.

tomcat/webapps/myapp/web.xml >

<error-page>
	   <error-code>404</error-code>
	   <location>/404test.cfm</location>
</error-page>

tomcat/webapps/myapp/404test.cfm >

<html>
<body>

<cfset subFolder = "#request.javax.servlet.error.request_uri#">
<cfoutput>#subfolder#</cfoutput>

</body>
</html>

In Lucee, if I request the non existant ‘test123’ file, via domain.com/test123, it returns the error I posted above.

In OpenBD, doing the same returns the .cfm file as requested with the output:

/test123

I then added various .cgi variables to each 404test.cfm page and realized something. The .cgi variables are referring the url of the 404 error page, not the url of the user requested page.

404test.cfm >

<cfoutput>#CGI.SCRIPT_NAME#</cfoutput>
<br><br>
<cfoutput>#CGI.REQUEST_URL#</cfoutput>

Yields browser output of

/404test.cfm 

http://domain com/404test.cfm 

This leads me back to why I think ‘javax.servlet.error.request_uri’ is being used here. It’s returning ‘test123’ from ‘domain. com/test123’ when the 404test.cfm is called.

So, if Lucee doesn’t support this method, I need to ask, what variable can I call to get the part of the requested url that is needed?

In Summary

User types ‘domain .com/test123’, but ‘test123’ isn’t a valid resource. Tomcat calls 404test.cfm, and from within 404test.cfm I need a variable that will provide me with the ‘test123’ portion of the url that was originally requested.

Thanks!

1 Like

I tried the code block posted in the guide. I replaced my 404test.cfm contents with the following code in Lucee

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

It didn’t error and returned the following results when calling domain.com/test123:

|string|javax.servlet.forward.request_uri = /test123|
|string|javax.servlet.forward.context_path =|
|string|javax.servlet.forward.servlet_path = /test123|
|string|javax.servlet.forward.mapping = org.apache.catalina.core.ApplicationMapping$MappingImpl@6cb88e2|
|string|sqlregex = (SELECT\s[\w\*\)\(\,\s]+\sFROM\s[\w]+)| (UPDATE\s[\w]+\sSET\s[\w\,\'\=]+)| (INSERT\sINTO\s[\d\w]+[\s\w\d\)\(\,]*\sVALUES\s\([\d\w\'\,\)]+)| (DELETE\sFROM\s[\d\w\'\=]+)| (DROP\sTABLE\s[\d\w\'\=]+)|
|string|javax.servlet.error.status_code = 404|
|string|javax.servlet.error.message = /test123|
|string|javax.servlet.error.servlet_name = default|
|string|javax.servlet.error.request_uri = /test123|

I’m going to play with this further, but wanted to post the results since you requested the test.

Using the information above I was able to reformat the code and get it to compute! yay.

old:
<cfset results.folder = "#request.javax.servlet.error.request_uri#">

new:
<cfset results.folder = getPageContext().getRequest().getAttribute( "javax.servlet.error.request_uri" )>

For the sake of posterity, is there a better way to get this information? Is this bad code (other than being cfml instead of cfscript in a cfc)? This is the first time I’ve had to deal with Lucee’s best practices.

What you have is fine I think. You’re needing to dig out values that are buried inside the Java servlet request, so it’s totally expected for you to tickle some of those underlying objects in the page context. To be clear, when I mentioned bad code in my previous post, I was only referring to IF you had code that tried to create your own variables called “requests” since that’s the name of a built in scope in CFML.

The only question we never really answered here was why your old code worked on OpenBD, but perhaps it doesn’t matter too much at this point. Like I said, it’s probably either an OpenBD feature, or a change in the way variables are looked up.

1 Like

Thanks!

I did some testing to see how OpenBD and Lucee would handle each variation of the request.

Lucee accepts:
<cfset results.folder = getPageContext().getRequest().getAttribute( "javax.servlet.error.request_uri" )>

Lucee rejects:
<cfset results.folder = "#request.javax.servlet.error.request_uri#">

OpenBD accepts:
<cfset results.folder = getPageContext().getRequest().getAttribute( "javax.servlet.error.request_uri" )>
<cfset results.folder = "#request.javax.servlet.error.request_uri#">

1 Like

@jasonAllenKing I think that what you’re doing there is a bit of an overkill, going for the Servlet attribute.

Can you check the CGI.QUERY_STRING in the 404 script? IIRC the original URL used to be there.

Keep in mind that this can be solved in an easier fashion by implementing the onMissingTemplate(targetPage) function in Application.cfc.

The problem is that right now you are handling the 404 in Tomcat, so Lucee doesn’t even know about the missing template. What you could do instead is add something like this in Application.cfc:

function onMissingTemplate(targetPage){
  // these two should log the same message but you should test to make sure:
  log text="#arguments.targetPage# was called";
  log text="#CGI.SCRIPT_NAME# was called";

  return true;  // indicate that the error has been handled, same as no-return, but added for clarity
}

You will have to remove this entry:

That way, Tomcat will still pass the request to Lucee and Lucee will handle it in the onMissingTemplate() function.

1 Like

I’m actually already doing that for .cfm files. When I remove the ‘error-code’ block from web.xml it just drops me to a default tomcat 404 page unless it’s a .cfm document. The script I’m looking at here in the OP is everything other than coldfusion files. In the past I’ve always used a custom 404 in Tomcat along with the missing template function in OpenBD. Basically I have had a custom 404 on both tomcat and OpenBD.

ex 1: domain.com/missingfolder --> Tomcat 404

ex 2: domain.com/missingFile.cfm --> lucee > onMissingTemplate

That said, I’m moving over to Lucee, and if there’s good practice way to configure tomcat to send everything to lucee regardless of the file extension or resource, that’d make things easier and cleaner. I guess really I need to address that in Tomcat… so I’ll look into that further.

I agree

I’ve been looking around for a few hours now and I’m not having much luck figuring out how to configure tomcat to forward all requests to Lucee, not just the default Lucee files.

Any ideas?