It is possible to enter an ampersand (&) in a String via Clarity and the stored value in the database will be '&'. For example, entering 'A&B' will store 'A&B' in the database.
Similarly, when using the REST API, the same value will also be stored as 'A&B'.
However, doing the same REST API calls via a GEL script will always escape the characters stored in the database to 'A&B'.
Steps to Reproduce:
Sample script:
(Pre-requisites - adjust the script if any pre-requisite is changed):
user', with all rightspassword'<gel:script xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wss="http://www.boomi.com/connector/wss" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xog="http://www.niku.com/xog" xmlns:x="jelly:org.apache.commons.jelly.tags.xml.XMLTagLibrary" xmlns:util="jelly:util" xmlns:sql="jelly:sql" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:jelly="jelly:core" xmlns:nikuq="http://www.niku.com/xog/Query" xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary" xmlns:file="jelly:com.niku.union.gel.FileTagLibrary" xmlns:core="jelly:core">
<!--***************************************Get the session from the system Start ***********************************--> <gel:parameter var="gel_host_user" default="user"/> <gel:parameter var="gel_host_pass" default="password"/> <gel:setDataSource dbId="niku"/> <!--Set parameter here End --> <!--***************************************Get the session from the system End ***********************************-->
<!-- Generate SessionID --> <core:new className="com.niku.union.security.DefaultSecurityIdentifier" var="secId"/> <core:invokeStatic var="userSessionCtrl" className="com.niku.union.security.UserSessionControllerFactory" method="getInstance"/> <core:set var="secId" value="${userSessionCtrl.init(gel_host_user, secId)}"/> <core:set var="sessionID" value="${secId.getSessionId()}"/>
<core:choose> <core:when test="${sessionID == null}"> <gel:log level="ERROR">Cannot login to Clarity XOG. Check username.</gel:log> </core:when> <core:otherwise> <gel:log>SessionID: ${sessionID}</gel:log> </core:otherwise> </core:choose>
<!--core:invoke method="setHeader" on="${patch}"> <core:arg type="java.lang.String" value="Cookie"/><core:arg type="java.lang.String" value="${v_Cookie}"/> </core:invoke--> <core:new var="patch" className="org.apache.http.client.methods.HttpPatch"> <core:arg value="https://<hostname>/ppm/rest/v1/projects/<instance>" type="java.lang.String"/> </core:new>
<core:invoke on="${patch}" method="setHeader"> <core:arg value="Authorization" type="java.lang.String"/> <core:arg value="Basic dXNlcjpwYXNzd29yZA==" type="java.lang.String"/> </core:invoke>
<core:invoke on="${patch}" method="setHeader"> <core:arg value="Content-Type" type="java.lang.String"/> <core:arg value="application/json" type="java.lang.String"/> </core:invoke> <core:set var="createProject" escapeText="false"><![CDATA[{"z_mystring":"A&B"}]]></core:set> <!-- <core:set var="createProject" escapeText="false">{"code": "${row.CODE}", "name": "${row.NAME}", "description":"${row.DESCRIPTION}" }</core:set> --> <core:new var="entity" className="org.apache.http.entity.StringEntity"> <core:arg value="${createProject}" type="java.lang.String"/> </core:new> <gel:log>entity: ${entity}</gel:log>
<core:invoke on="${patch}" method="setEntity"> <core:arg value="${entity}" type="org.apache.http.entity.StringEntity"/> </core:invoke> <gel:log>patch: ${patch}</gel:log>
<core:invokeStatic var="httpclient" className="org.apache.http.impl.client.HttpClients" method="createDefault"/> <core:invoke var="response" on="${httpclient}" method="execute"> <core:arg value="${patch}" type="org.apache.http.client.methods.HttpPatch"/> </core:invoke> <gel:log>response: ${response}</gel:log>
<core:invoke var="entityResponse" on="${response}" method="getEntity"/> <core:invoke var="ResponseStatus" on="${response}" method="getStatusLine"/> <gel:log>ResponseStatus getProtocolVersion: ${ResponseStatus.getProtocolVersion()}</gel:log> <gel:log>ResponseStatus getReasonPhrase: ${ResponseStatus.getReasonPhrase()}</gel:log> <gel:log>ResponseStatus getStatusCode: ${ResponseStatus.getStatusCode()}</gel:log> <gel:log>entityResponse: ${entityResponse}</gel:log> <core:set var="void" value="${response.close()}"/>
<gel:log>exception::${exception}</gel:log></gel:script>
Expected Results: Value stored is 'A&B' - same as when using Clarity or the REST API without a GEL script.
Actual Results: Value stored is 'A&B'.
Any Clarity supported version.
According to the Expected Results, the script is not correct:
<core:set var="createProject" escapeText="false"><![CDATA[{"z_mystring":"A&B"}]]></core:set>
The way the createProject variable is declared, the variable's content will get encoded (replacing & with &).
To avoid the encoding, the variable needs to be declared as follows:
<core:set var="createProject" encode="0"><![CDATA[{"z_mystring":"A&B"}]]></core:set>
This tag sets a variable from the result of an expression.
encode
When set to:
Use this only if this tag is specified with no value so that the text body of this tag can be used as the body.
Type: Boolean