tracker issue : CF-4203443

select a category, or use search below
(searches all categories and all time range)

Session scope java integration has case sensitivity issues

| View in Tracker

Status/Resolution/Reason: To Test//Fixed

Reporter/Name(from Bugbase): Ryan Cogswell / ()

Created: 11/06/2018

Components: Java Integration

Versions: 2018

Failure Type: Incorrectly functioning

Found In Build/Fixed In Build: 2018,0,01,311402 /

Priority/Frequency: Normal / All users will encounter

Locale/System: English / Windows 7 64-bit

Vote Count: 0

Problem Description: 

When using J2EE sessions, the Session scope is exposed in Java as a Map which can be retrieved from the HttpSession by getting the session attribute keyed by the application name. The full type of this Map is coldfusion.runtime.J2eeSessionScopeStub. However, when ColdFusion accesses the Session scope, it doesn't appear to use J2eeSessionScopeStub, but rather it uses the J2eeSessionScope that is wrapped by the stub.

The issue is that J2eeSessionScopeStub only behaves correctly for the "get" and "put" operations. Other Map methods such as "remove" and "containsKey" behave in a case-sensitive manner and behave inconsistently with "get" (e.g. containsKey can return false, but get will still work)

Steps to Reproduce:

ColdFusion must be configured to use J2EE sessions. Then put the following code into a cfm page to test:

<cfapplication name="myApp" sessionmanagement="yes">
<cfset StructClear(Session)>
<cfset Session.TestKey1 = "TestValue1">
<cfdump var="#Session#" label="Session">

<cfset sessionFromJava = GetPageContext().getRequest().getSession().getAttribute(application.applicationname)>
<cfset classNameFromJava = sessionFromJava.getClass().getName()>
<cfset sessionFromCF = GetPageContext().findAttribute("Session", false)>
<cfset classNameFromCF = sessionFromCF.getClass().getName()>
	#classNameFromJava# containsKey: #sessionFromJava.containsKey("TestKey1")#<br>
	#classNameFromJava# get: #sessionFromJava.get("TestKey1")#<br>
	<cfset sessionFromJava.remove("TestKey1")>
	#classNameFromJava# get after remove: #sessionFromJava.get("TestKey1")#<br>
	#classNameFromCF# containsKey: #sessionFromCF.containsKey("TestKey1")#<br>
	#classNameFromCF# get: #sessionFromCF.get("TestKey1")#<br>
	<cfset sessionFromCF.remove("TestKey1")>
	#classNameFromCF# containsKey after remove: #sessionFromCF.containsKey("TestKey1")#<br>
	#classNameFromCF# get after remove: #sessionFromCF.get("TestKey1")#<br>

Actual Result:
When using sessionFromJava in the code above, the "containsKey" and "remove" methods do not work correctly ("containsKey" returns false when it should return true and "remove" fails to remove the entry). This appears to be because it uses implementations from AbstractMap which then are case-sensitive rather than case-insensitive.

Expected Result:
All of the Map methods should be delegated from J2eeSessionScopeStub to J2eeSessionScope rather than just "get" and "put". This would cause them to work as expected and, for instance, the "remove" method in Java would then work similarly to StructDelete from CF and containsKey would work as expected.

Any Workarounds:
There are two main workarounds. When using the Map methods other than "get" and "put" in Java, pass the key in as lowercase:
map.put("TestKey1", "TestValue1");
map.containsKey("TestKey1".toLowerCase()); // returns true
The other workaround is to use reflection to call "getJ2eeSessionScope" on the J2eeSessionScopeStub  Map and use the J2eeSessionScope Map returned by that method instead.

This bug is not new to CF 2018. The bug for sure exists back through CF 10 and probably back further.