Nulls enabled in cf2018 though Enable Null Support is turned off - coldfusion

We're upgrading some of our applications from CF10 to CF2018.
On CF2018, we've unchecked 'Enable Null Support' in the ColdFusion Administrator, and we can see when we output the value of enableNullSupport that it is set to NO. However, but we're still seeing behaviour which suggests that Nulls are enabled.
e.g. When we create an object with a property (eg FirstName) which is not initialised, the expression getFirstName() eq "", which previously was true, is now false and IsNull(getFirstName()) is true
The article on Null support in ColdFusion 2018 says:
Now in your ColdFusion applications, you can assign null to a
variable, as shown below:
<cfset price = null>
But if you try this line at https://cffiddle.org (with CF2018 selected), you get - Variable NULL is undefined.
It looks like the documentation around support for Null is misleading.

I contacted Adobe Support, who were able to replicate the issue, and came back to confirm that it was a bug.
They sent me a patch which has fixed the issue. The patch will be included in a future update to cf2018

Related

enable/disabling tracking consent with sitecore 10.1

Has anyone worked with enabling/disabling tracking consent with sitecore 10.1?
I tried the below but it does not seem to work as consentChoice.IsGiven is always returned as true(even after the revoke code is executed):
: https://doc.sitecore.com/xp/en/developers/101/sitecore-experience-platform/manage-a-contact-s-tracking-consent-choices.html
Also, when I set explicitConsentForTrackingIsRequired to true for my site the tracking code starts giving an error.
Regarding
consentChoice.IsGiven always returning true, my initial suspect is your browser cache, your previous site visit might have already captured or set SC_TRACKING_CONSENT (which is set on call to GiveConsent) , if this cookie exists consentChoice.IsGiven is always read from here.
You may need to test this better with either incognito(if using chrome also ensure no shared incognitos) or ensure to force hard refresh (clear cookies) before testing this.
Tracking error code you are facing when explicitConsentForTrackingIsRequired is set to true, this could be due to multiple issues -> ensure xDB tracker is enabled before enabling the consent setting, or check if you have any code attempt to explicitly Start Tracking or access to Tracker.Current.Contact before User Consent has been given. This may throw random errors and error log would help pin point these if you have better example of errors facing.
In addition to these I had also faced errors using this in conjunction with sitecore forms:
When using forms along with explicitConsentForTrackingIsRequired there is an issue where forms auto starts tracking on interaction with form elements , forms has a missing condition check for User Consent before starting tracking.
Please check the answer here for workaround if it is the case.

Undocumented inconsistent behavior regarding ColdFusion's CGI scope/struct

I initially posted this as an answer to this question earlier regarding Empty CGI.REDIRECT_URL on ColdFusion 2016. After thinking about it, I thought better of it since technically didn't answer the OP's question. Instead I decided to make it into a separate question, even though it's more of a commentary than a question. While this technically might not meet the full requirements of a Minimal, Complete, and Verifiable example and people might ding me with downvotes, I decided it was worth it anyway in the hope that it will become easier to find for future CFers who might encounter this. Thus preventing them from banging their head against the wall regarding this peculiar behavior of the CGI struct/scope.
With that said, the CGI struct/scope has some undocumented inconsistent behavior from other structs/scopes. Note that I personally take no credit for this discovery since I happened across this some time ago upon reading Ben Nadel's blog post on this. So all the information I'm posting here is already detailed there, but I wanted to write a nice summary here on SO.
Undocumented behavior 1 - Unlike other structures, if a CGI struct key doesn't exist, then it won't throw an error when referencing it.
In the OP's original question, he was wondering why cgi.REDIRECT_URL existed but was empty. As he eventually found out, it never actually existed. As a separate example you can execute this line of code without throwing an error. Not what you'd expect, huh?
<cfoutout>#cgi.THIS_IS_A_FAKE_KEY#</cfoutout>
So what's a CFer to do? Test for the key existence.
<cfif structKeyExists( CGI, 'THIS_IS_A_FAKE_KEY' )>
THIS_IS_A_FAKE_KEY exists
<cfelse>
THIS_IS_A_FAKE_KEY doesn't exist
</cfif>
Undocumented behavior 2 - Unlike other structures, if you dump the CGI struct, it won't display all the key/value pairs, it will only display a defined set of keys.
In the OP's case, he had a custom Apache CGI variable cgi.REDIRECT_URL that was used in his code prior to upgrading to CF2016 and was able to refer to it directly. However, I'm presuming if he dumped out the cgi struct, it wouldn't appear in the dump. In Ben Nadel's case, he also had a custom cgi variable called cgi.document_root that was passed through from a load balancer and was able to refer to it directly, but he also wasn't able to see the key when dumping the cgi contents.
So what's a CFer to do? Understand this and store it in the back of your mind so you won't get bitten when you dump the cgi contents and the key/value pair isn't there. Other than that, not much else.
I went in to the cfusion.jar file of ColdFusion. What I found there was a bit confusing.
CGI scope is not of a structure form as one would hope for.
This is how a call for CGI variable is handled. eg <cfoutout>#cgi.THIS_IS_A_FAKE_KEY#</cfoutout>
The normal valid CGI scope variables are the ones in this list and these will be initialized to "" by default.
private static final String[] names ="AUTH_PASSWORD","AUTH_TYPE","AUTH_USER","CERT_COOKIE","CERT_FLAGS","CERT_ISSUER","CERT_KEYSIZE","CERT_SECRETKEYSIZE","CERT_SERIALNUMBER","CERT_SERVER_ISSUER","CERT_SERVER_SUBJECT","CERT_SUBJECT","CF_TEMPLATE_PATH","CONTENT_LENGTH","CONTENT_TYPE","CONTEXT_PATH","GATEWAY_INTERFACE","HTTP_ACCEPT","HTTP_ACCEPT_ENCODING","HTTP_ACCEPT_LANGUAGE","HTTP_CONNECTION","HTTP_COOKIE","HTTP_HOST","HTTP_USER_AGENT","HTTP_REFERER","HTTP_URL","HTTPS","HTTPS_KEYSIZE","HTTPS_SECRETKEYSIZE","HTTPS_SERVER_ISSUER","HTTPS_SERVER_SUBJECT","LOCAL_ADDR","PATH_INFO","PATH_TRANSLATED","QUERY_STRING","REMOTE_ADDR","REMOTE_HOST","REMOTE_USER","REQUEST_METHOD","SCRIPT_NAME","SERVER_NAME","SERVER_PORT","SERVER_PORT_SECURE","SERVER_PROTOCOL","SERVER_SOFTWARE","WEB_SERVER_API" };`
Also all of these values also come from various java libraries javax.servlet, HttpServletRequest etc.
If the requested variable is not any of these after a bit of checks, ColdFusion goes to the request headers. You can see these using getHttpRequestData().headers. Then looks for a key there with hyphens(-) instead of the underscores(_) in the cgi key request. (If the key starts with http_, then the key in the request headers will be with out it like this http_x_forward in request header will be x-forward)
value = request.getHeader(name.replace('_', '-'));
From what I understand as far as ColdFusion is concerned the keys, mentioned in the first point are the recognized as part of the CGI scope. But when there is additional information passed from a Apache load balancer server to ColdFusion, those end up in the request headers. Since the java getHeader just returns a blank string (or something with data type undefined) instead of a undefined error, ColdFusion does not identify any of the keys is defined or not.
So if the key THIS_IS_A_FAKE_KEY is sent to ColdFusion from an intermediary such as an Apache server. You will find that in the getHttpRequestData().headers['THIS-IS-A-FAKE-KEY'] but not on the CGI scope dump.
That being said my personal opinion is that it is better to check directly in the getHttpRequestData().headers for custom CGI variables other than in the scope itself.
EDIT Thanks to Ageax for pointing out one of my test cases was invalid on my earlier revision of this post.
Great bit of detective work RRK! So I decided to perform an experiment to verify your finding by creating two loops. The first loop will display the key/value pairs from getHttpRequestData().headers and the second loop does the same using the corresponding key/value pairs from the cgi scope by replacing the - with _. Voila! as reported by RRK, we can see how you can obtain the values by either method. I made an updated gist and posted here for anyone interested.
<cfset httpHeaders = getHttpRequestData().headers>
<h3>getHttpRequestData().headers</h3>
<cfloop collection="#httpHeaders#" item="key" >
<cfoutput><strong>#Key#</strong> : #httpHeaders[key]#<br></cfoutput>
</cfloop>
<h3>cgi keys dash to underscore</h3>
<cfloop collection="#httpHeaders#" item="key" >
<cfset keyUnderscore = replace(key, "-", "_", "all")>
<cfoutput><strong>#keyUnderscore#</strong> : #cgi[keyUnderscore]#<br></cfoutput>
</cfloop>

Sitecore workflow - publishing item in draft state

I am currently working with sitecore items that are in a draft workflow state. The following happens:
Create an item that will go into workflow draft state
Publish the item/publish the parent item (with sub items selected) to the web db from master db, ignore publish warning prompt
The item will appear in the web database but with no versions
This causes our controls to render the item but with standard values because there are no versions. Of course we could add a check for item.Versions.Count > 0 but my question is why this is happening?
Surely an item in draft workflow state should never appear in the web database in any way?
The workflow being used is pretty standard and has no customisation. The states and commands are:
Draft
Submit
Awaiting approval
Reject
Approve
Validation action
Approved
Auto publish
Thanks in advance.
I believe you can use the following property on each of your site nodes in the config.
<site name="website" filterItems="true" ... />
If setting this to true doesn't resolve the issue then you can add the following pipeline step, in addition to the above setting, before the Sitecore.Pipelines.FilterItem.EnsureFilteredItem step.
public class HideEmptyItem
{
public void Process(FilterItemPipelineArgs args)
{
if ((Context.Site != null && Context.Site.DisplayMode == DisplayMode.Normal) && args.Item.Paths.Path.StartsWith("/sitecore/content/"))
{
try
{
Context.Site.DisableFiltering = true;
if (args.Item.Database.GetItem(args.Item.ID, Context.Language).Versions.Count == 0)
{
args.FilteredItem = null;
}
}
finally
{
Context.Site.DisableFiltering = false;
}
}
}
}
Also ensure the following is set accordingly, the default is false;
<setting name="Publishing.PublishEmptyItems" value="false" />
I actually encountered this issue but in a different way. If you use publishing restrictions you can end up with an item that has no versions on it but can still be published. There are many ways for an item to end up with no versions, not just a new item with a single version that hasn't been pushed through a workflow. The above fix was actually provided by Sitecore support and worked for me.
If this doesn't work for you then I would suggest adding in check when items are published to see if they have any versions, although I believe that's what the fix above is supposed to do.
EDIT: Changed property from "hideEmptyItems" to "filterItems" and added further explanation.
My personal opinion is that you should be checking for version count. If you plan on ever supporting a multilingual site, it is entirely possible to have a version in one language, but not another (not approved yet in Spanish, for example). You would want your controls to handle that scenario (or execute fallback).
It is entirely valid that the current user in the current language may have no valid versions come back for them. I would expect that the business logic of the web controls should handle those scenarios.
To explicitly answer your question, this happens because the item is not null but it has no versions. A version is a dimension of an item and it happens to be "empty" if you have no version. So your code gets a valid non null item, but has no field values since there is no version and thus your controls don't fill with data.
This will only happen for new items. Example: create an item and you have v1 which is is in draft. You "publish" the item. The item goes out to the web DB but the v1 dimension of it does not, so you're left with a non null item with no versions.
As Jay said, the solution is to check for this when you query items.
First, the default workflow should set to the item's template "__Standard Values".
Second, workflow with "admin" account doesn't work. Try another account.

Amazon CloudSearch - documents not deleted from index

I have a problem deleting documents from Amazon CloudSearch.
When I send document for deletion I receive response
{"status": "success", "adds": 0, "deletes": 5}
And then the video stays in the index with all fields reset to their default values and not deleted.
The documentation is not clear if this is the normal behaviour or a bug.
Any one else experienced this?
This surprised me too but appears to be normal behavior. The 'deleted' documents aren't searchable anymore since their fields are all null so they shouldn't cause any problems.
The problem I have with this is that they can be returned if you search for something like "-zomgwtfbbq", since they don't contain the term "zomgwtfbbq".
It is also confusing since it makes your dashboard show one count (the "searchable" documents) but if you run a test search for -zomgwtfbbq (what I have been using as a proxy for "get all documents"), you get a different number. Took me a while to figure out why.
Despite what they say about setting the version to max uint32 "permanently removing" the document, it will still be there. The problem is that they consider these documents unsearchable, but they're not.
Are you specifying the version number when you delete the document?
When deleting documents, note that deleting version max(uint32_t) will permanently remove the document from your domain. Because it is not possible to specify a higher version number, there is no way to add a later version of the document.
http://docs.aws.amazon.com/cloudsearch/latest/developerguide/versioning.html

Sitecore: Seemingly Random errors appear

we are experiencing some very odd errors in our installation.
Some times out of nowhere Sitecore throws an error:
Assert: Value Cannot be null. Parameter: Item.
The closest i have come to identifying the problem is narrowing it down to either an index or the web database.
Anyway, if I log into sitecore the Item is just missing, i can fix it in 3 ways:
Rebuild the index.
Recycle app pool
iisreset
Does any of you have an idea why this might be happening? We are running Sitecore.NET 6.5.0 (rev. 120706). Any help will be deeply appreciated.
You are describing a system stability issue, so I recommend opening a ticket with Sitecore support (http://support.sitecore.net). This sort of issue is difficult to troubleshoot over Stack Overflow, since we do not have access to your logs and configuration.
When opening the ticket, I recommend using the Support Package Generator which bundles up all the information (Web.config, App_Config files, IIS settings, Sitecore log files) that Sitecore Support needs to troubleshoot the issue. It's a pretty nifty tool.
That said, from what you describe, it sounds like the issue is related to caching. The fact that restarting IIS resolves the issue indicates that the item is in the Web database, but the runtime doesn't see it. You can prove out whether this is the issue by clearing cache using the /sitecore/admin/cache.aspx screen. If your cache is not getting updated properly, you should review your configuration against the guidelines in the SDN Scaling Guide.
Based on knowing you're using the Advanced Database Crawler, your issue may be how you're converting a SkinnyItem to an Item. I've had this issue before. If you look at the SkinnyItem.cs class, there's a GetItem() method to convert it into an Item. You can see it uses the database to get the item by its ID, language, and version number. Its possible that when you publish from master to web, you are publishing a new version # of an existing item and thus the new version exists in the web DB, but the index is not updated and references the old version. So, this GetItem() call would use the previous version # and the item would be null. One way to fix this is instead of calling that GetItem() method, just use your own code to get the latest version of that item from Sitecore, e.g.
Item item = Sitecore.Context.Database.GetItem(someSkinnyItem.ItemID);
Instead of
Item item = someSkinnyItem.GetItem();
Here's an example flow:
Foo item created in master DB as version 1.
Publish Foo to web
Index will pick up version 1 in web DB and put in index.
Any querying code against index will convert the SkinnyItem to an Item via that GetItem() method and will pass 1 as the version #.
Page will load, no error in log
Back in master, create version 2 of Foo and publish.
Index may not get updated right away or even if configured wrong.
Code that looks against index will call GetItem() and still call with version 1 since that's in the index
But when you published, web no longer has version 1, it now has version 2, and thus that specific version of that item Foo is null
Error shows in log
On a similar note, here's a blog post by Alex Shyba (creator of the ADC) on how to sync HTML cache clearing with the index updates. That may help.