JSSP pages are server-side public web pages in Adobe Campaign Classic. Here are some info about it. It will result in pages with the .jssp extension.
JSSP Origin
JSSP come from a custom implementation of the Java JSSP project, description and docs here, based on multiple Java EE objects such as the HttpServletRequest class.
Note: Adobe Campaign Classic JSSP are built on top of the JSSP initial project, so many JSSP methods are not available.
Basic JSSP page
Create a JSSP in any JSSP folder. The JSSP name will define the URL:
The name my_nms:my-page.jssp
gives the URL https://xxx.campaign.adobe.com/my_nms/my-page.jssp
.
No need to publish, no cache, the page is instantly available:
Note: Some clients may give an error as the Header Content-Type is not defined. I.e. in Restlet Client:
To fix it, add the content type in Javascript with response.setContentType('text/html;charset=utf-8'); %>
:
<%
response.setContentType("text/html;charset=utf-8");
%>
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Title here</title>
</head>
<body>
Body Here
</body>
</html>
Existing ACC web portal
Accessible via https://myinstance/view/home
, with source code in xtk:dashboardNavigation.js
.
NL.ns('NL.Dashboard')
NL.require('/nl/core/shared/core.js')
NL.Dashboard.init(request, response, options, callback)
NL.require("/nl/core/shared/dashboard.js")
var jsspContext = new NL.JSSPContext(request)
jsspContext.checkAuthentication(response)
if(!options.noClientOutput)
<!DOCTYPE html PUBLIC><html><head>
NL.client.deps()
fromdepman.js
<!-- deps in mode " + mode.name + '/' + this.lang + " -->
(<!-- deps in mode min/en -->
)<script src='" + fn + extraQS + "'"
, examples:/nl/gen/min/WA-70839cda0b8c2a1d4b025f0ca36ccd71.js
forJSON2, NL.QueryDef, NL.Cookie...
/nl/gen/min/WA-en-cf461481d56f1e56aa870f98218b501b.js
for stringgroup/nl/gen/min/nlsrc-5958223c29a2051c0944e40651cd2548.js
forjquery-ui, NL.Widgets, NL.UI...
/nl/gen/min/nlsrc-en-42e5495a630485dbd63f8ddcd2169a9b.js
for stringgroup
<!-- END deps in mode " + mode.name + " -->
(<!-- END deps in mode min -->
)
controller = new NL.UI.Controller({pageController: true})
jsspContext.genClientSessionInitCode()
var nls = NL.session;
nls.buildNumber =
document.__securitytoken = "' + NL.JS.escape(newSecurityToken) + '";'
var dashboardContext = {
Advanced: GET JSON API to get Recipient via JSSP
<%
response.setContentType('application/json');
var x = {'a':'b'};
document.write(JSON.stringify(x));
%>
But var delivery = NLWS.nmsDelivery.load('12435');
results in an Access Denied:
XTK-170019 Access denied.
This is because the current operator is Anonymous:
<% for(var i in application.operator){
document.write(i+': '+application.operator[i]+'\n');
} %>
Displays
login:
id: 0
computeString: Anonymous account
groups:
rights:
timezone: America/Los_Angeles
locale: en-US
home:
So we have to change the logon information with the logon
function:
<% var oldContext = logonEscalation('webapp'); // login with the standard webapp access
for(var i in application.operator){
document.write(i+': '+application.operator[i]+'\n');
}
logon(oldContext); // log back in as previous user
logon(sessionToken); // log in with token %>
Displays
login: webapp
id: 3420
computeString: Web applications agent (webapp)
groups:
rights: ADMINISTRATION
timezone:
locale:
home:
Database is now accessible 😉
Use below code to create a standard GET Json API with a Dynamic JavaScript Server Page named fco:fco-test-json-get-api.jssp
:
<%
response.setContentType('application/json');
if(request['method'] != 'GET'){
return document.write(JSON.stringify({status:'KO',error:'Please use HTTP GET'}));
}
var label = request.getParameter('label'); // fetch "label" param from URL
if(!label){
return document.write(JSON.stringify({status:'KO',error:'Missing "label" param'}));
}
logonEscalation('webapp'); // logon as webapp operator
var query = NLWS.xtkQueryDef.create({queryDef: {
schema: 'nms:delivery', operation: 'select', lineCount: 500, // /!\ lineCount defaults to 10,000
select: { node: [
{expr: '@id'},
{expr: '@label'},
]},
where: {
condition: [
{expr: "Lower(@label) LIKE '%"+label+"%'"}, // filter by label
],
}
}});
var records = query.ExecuteQuery(); // DOMElement
var deliveries = [];
for each(var record in records.getElements()){
deliveries.push({
id: record.$id,
label: record.$label,
});
}
var result = {
status: 'OK',
length: records.getElements().length,
results: deliveries,
}
document.write(JSON.stringify(result));
%>
Advanced: POST JSON API to update Recipient via JSSP
<%
response.setContentType('application/json');
if(request['method'] != 'POST'){
return document.write(JSON.stringify({status:'KO',error:'Please use HTTP POST'}));
}
var body = request.getBodyAsString();
var bodyAsJson = JSON.parse(body);
if(!bodyAsJson.recipientId){
return document.write(JSON.stringify({status:'KO',error:'Missing "recipientId" key'}));
}
logonEscalation('webapp');
var recipient = NLWS.nmsRecipient.load(bodyAsJson.recipientId);
var result = {
status: 'OK',
length: 1,
results: [{
firstName: recipient.firstName,
createdDate: recipient.created,
}],
}
document.write(JSON.stringify(result));
%>
HttpServletRequest documentation
<%
// disable cache
response.addHeader("Pragma", "no-cache");
response.addHeader("Cache-Control", "no-cache");
response.addHeader("Expires", new Date().toGMTString());
// content type
response.setContentType("text/html;charset=utf-8");
%>
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Title here</title>
</head>
<body>
<b>URL param1:</b> <%= request.getParameter("param1") %><br>
<b>HTTP Body: getBodyAsString():</b> <%= request.getBodyAsString() %><br>--<br>
<% for(var key in request){
document.write("<b>"+key+":</b> "+request[key]+"<br>")
} %>
<br>--<br>
<b>User-Agent:</b> <%= request.getHeader('User-Agent') %><br>
<b>X-Forwarded-For:</b> <%= request.getHeader('X-Forwarded-For') %><br> <!-- IP address -->
<b>getRemoteAddr():</b> <%= request.getRemoteAddr() %><br> <!-- IP address and proxy -->
</body>
</html>
Output:
URL param1: value1
HTTP Body: getBodyAsString(): paramPost1=val1¶mPost2=val2
--
parameters : [object RequestParameters]
cookies : [object Cookies]
requestURI : /my_nms/my-page.jssp
requestURL : http://campaign.adobe.com/my_nms/my-page.jssp
queryString : param1=value1
servletPath : /my_nms/my-page.jssp
contextPath :
pathInfo : null
serverName : campaign.adobe.com
serverPort : 80
serverURL : https://campaign.adobe.com
attributes : [object RequestParameters]
method : POST
--
User-Agent: Mozilla...
X-Forwarded-For: A.B.C.D, E.F.G.H
getRemoteAddr(): E.F.G.H
See https://en.wikipedia.org/wiki/List_of_HTTP_header_fields for list of header names.
HttpServletResponse documentation
Noticed that we used <% response.[...] %>
, what properties and methods are available? Response is of type HttpServletResponse
.
JS doc for HttpServletRequest
// Methods/** Changes the document type of the response. */
setContentType(string type)
/** Returns a temporary redirection to another URL. */
sendRedirect(string url)
/** Adds a cookie to the response. */
addCookie(string cookie)
/** Adds an additional HTTP header to the response. */
addHeader(string key, string value)
/** Returns an error response using the error code passed as a parameter. */
sendError(int httpErrorCode)
Explore HttpServletRequest API
// Methods
/** Returns an attribute defined in the query header. */
getHeader(string key)
/** Returns the value of a query parameter. */
getParameter(string key)
/** Returns the IP address of the client or the last proxy to have sent a request. */
getRemoteAddr()
/** Returns the value (coded in UTF-8) of a parameter of the query. */
getUTF8Parameter(string key)
/** Returns the body of the query in the form of a string of characters using query coding. */
getBodyAsString()
/** Redirects the query towards another page without going via the client. */
forward(string url)
// properties
/** Returns the query parameters. */
parameters
/** Returns the cookies of the query. */
cookies
/** Returns the URL of the query. */
requestURI
/** Returns the part of the query's URL which matches the parameters. */
queryString
/** Returns the name of the protocol used (HTTP, HTTPS, etc.) to access this page. */
scheme
/** Returns the name of the query server. */
serverName
/** Returns the port number used to contact the server. */
serverPort
/** Returns the URL for accessing the server. */
serverURL
/** Returns the section of the query's URL which matches the servlet. */
servletPath
/** Returns the section of the query's URL which matches the context. */
contextPath
/** Returns the additional information of the query's URL. */
pathInfo
/** Returns a string of characters containing the HTTP method used to call up this query (GET, HEAD, POST, etc.). */
method
Encode and decode URL
/** Convert string to URL safe equivalent */
encodeURI(string)
encodeURI("Hello world?!'=-") // "Hello%20world?!'=-"
// encodeURI can be used on a full URL, without messing with : / ? or &
encodeURI("https://example.com?var1=val1&var2=val2") // "https://example.com?var1=val1&var2=val2"
/** Convert string from URL safe */
decodeURI(string)
decodeURI("Hello%20world?!'=-") // "Hello world?!'=-"