Showing posts with label Knowledgebase. Show all posts
Showing posts with label Knowledgebase. Show all posts

Wednesday, March 21, 2012

Installing PostgreSQL 9.1.3 on Mac OS X Lion

Unsatisfied and undaunted by the foreboding discussion on installation troubles ("PostgreSQL 9.1 Installer Fails on OS X Lion"), I decided to follow the official PostgreSQL instructions to install the software from source. All so that I could build Ruby on Rails apps to be deployed to Heroku.

Note: PostgreSQL 9.0.5 appeared to have been bundled with my Lion installation, as seen with pg_config before installing 9.1.3. But I wasn't sure how well it worked since Apple provides zero documentation on this bundled installation, and initdb was not located in a known path.

So, in short, here are the steps I followed to install PostgreSQL 9.1.3 on Mac OS X Lion 10.7.3 from the source code.

# Make sure you have the latest version of
# GNU Make for Mac OS X. This can be downloaded
# through Xcode 4.3 by installing the Command
# Line Tools.

# Download the source code from the PostgreSQL
# website, and start this procedure in the
# expanded directory containing the source files.

./configure
make
sudo make install

# At this point, assuming installation was
# successful, create a new user to serve as the
# unprivileged user that will own the server
# process.

# Open System Preferences to create a new user.
# New Account:  Standard
# Full Name:    PostgreSQL Agent
# Account name: postgres

cd /usr/local/pgsql/
sudo mkdir data
sudo chown postgres data
sudo mkdir log
sudo chown postgres log

# At this point, we're done with configuration
# and ready to start the server process.

sudo su - postgres

# The following commands will be run as the
# PostgreSQL Agent user.

cd /usr/local/pgsql/
bin/initdb -D data/
bin/postgres -D data/ >log/logfile 2>&1 &

# To verify that the server is working properly,
# let's create a test database and see whether
# we can connect using the interactive terminal.

bin/createdb test
bin/psql test

If all went well, you should see something like the screenshot below.


Finally, we can move on to the fun stuff!

Friday, March 2, 2012

Installing Ruby 1.9.2 on Mac OS X Lion 10.7.3

A few simple steps to get Ruby 1.9.2 up and running on Mac OS X Lion 10.7.3:
  1. Download Xcode from the App Store.
  2. Run Xcode and open the app's Preferences.
  3. Open the Downloads tab, then download and install Command Line Tools for Xcode.
  4. Download and expand Ruby 1.9.2 (stable) source from the official Ruby website.
  5. Launch the Terminal app.
  6. Change to the directory containing the expanded Ruby source code.
  7. $ ./configure
  8. $ make
  9. $ sudo make install

Then, to use the newly installed version of Ruby (instead of the pre-installed version that came with Lion):
$ export PATH=/usr/local/bin:$PATH

To summarize the results... Before installing Ruby 1.9.2:
$ irb -v
irb 0.9.5(05/04/13)
$ ruby --version
ruby 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin11.0]

After installing Ruby 1.9.2:
$ ruby --version
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.3.0]
$ irb -v
irb 0.9.6(09/06/30)

Thank you, Mike Clark, for pointing out that with Lion I now have to download Command Line Tools for Xcode in order to compile stuff.



Thank you, Ubuntu community, for giving instructions on how to compile programs from source code.

... And finally, with no further ado, I present: the rant behind this post!

Programming an application is supposed to be difficult and require significant thinking. Installing the compiler or interpreter or whatever package is necessary to run the code should be easy.

Maybe it's just me... but why in the world did it take me 2 hours and so much frustration to get Ruby setup on my Mac? Ruby's website says, "Compiling from Source is the standard way that software has been delivered for many, many years. This will be most familiar to the largest number of software developers." Thanks. For assuming incorrectly that I know how to "compile from source" and providing zero instructions for how to do that on my OS.

Thursday, December 22, 2011

Org ID Automatically Replaced in Sandboxes

I discovered something that made my blood run cold today: The OrganizationInfo.isProduction method I was relying on in Apex to communicate to the correct web service endpoint was returning true in my sandbox orgs.

My OrganizationInfo class is super simple, created as suggested in a comment on the IdeaExchange (Determine sandbox name vs production from apex). Shown below for reference:

public class OrganizationInfo {
    
    /**
     * The Organization ID of the production org.
     */    
    private static final Id PRODUCTION_ID =
            '00DA0000000Kb9R';
    
    /**
     * Determine whether the current org is a
     * production org or a sandbox org,
     * based on whether the Org ID matches the
     * production App org's Org ID.
     *
     * @return Whether the org is Production
     */
    public static Boolean isProduction() {
        return UserInfo.getOrganizationId()
                == PRODUCTION_ID;
    }   // public static Boolean isProduction()
    
}   // public class OrganizationInfo

The obvious question: How does something so simple fail in a sandbox org?

The surprising answer: When a sandbox is created or refreshed, Salesforce automatically does a search and replace and replaces the production org ID with the sandbox org ID. Once a sandbox is created or refreshed, a single line of code changes in the above class:

    private static final Id PRODUCTION_ID =
            '00DZ000000056dv';

This tiny, almost unnoticeable change has been screwing everything up for a long time, and its discovery also explains why we would periodically get strange data in production and also strange responses in our sandboxes.

I wish I had known about this earlier, but who would've guessed? Anyhow, the fix that I've implemented (and confirmed by creating a new sandbox) is to split the ID into 3 parts when assigning it to the constant.

    private static final Id PRODUCTION_ID =
            '00DA0' + '00000' + '0Kb9R';

Amazing... the things one discovers in the worst possible ways...

Friday, November 25, 2011

Using IsPersonAccount Field in Account Triggers

Great news! It looks like the IsPersonAccount field is always available for use in Apex triggers, without the need to retrieve the field values using SOQL!

The following test was used to reach this conclusion (in Winter '12):
  1. Create a trigger that activates or fires before/after insert, before/after update and before/after delete.
  2. Add code to the trigger to check every record in Trigger.new and in Trigger.old with the following assertion: System.assert(accountInTrigger.get('ispersonaccount') != null);
  3. Create a test method to insert, update and then delete an Account.
  4. Verify that the test passes.

Optionally, one can also use the following code in the trigger to take a deeper look at the basic information that's always available, depending on what caused the trigger to fire:
System.debug('Trigger.new = ' + Trigger.new);
System.debug('Trigger.old = ' + Trigger.old);

Monday, November 7, 2011

assertEquals Method for Multi-Select Picklist Values or Other Delimited Values

I couldn't find a way to easily assert that two multi-select picklist values are identical, especially considering that 'value1;value2' really should be considered equal to 'value2;value1'.

To fix this, I wrote an auxiliary class System2 that has a custom assertEquals method that asserts two Strings contain the same delimited values.

The code is verified by checking the following cases in an associated test class:

s1s2result
pass
afail
afail
aapass
aa;bfail
a;bafail
a;ba;bpass
b;aa;bpass
a;bb;apass
a;b;cc;a;bpass
b;a;ca;b;cpass
a;b;ca;b;c;dfail
a;b;c;da;b;cfail

Saturday, November 5, 2011

JavaScript Hack to Render Red Bar for Required apex:selectList

I'm surprised that Salesforce doesn't support rendering apex:pageBlockSectionItem elements with the same red bar that identifies a required element.

All I wanted was for ...


... to look like ...


So, for consistency of developing a Visualforce page that has a consistent look-and-feel, I came up with a script snippet that seems to work to add the red bar to any apex:pageBlockSectionItem with the dataStyleClass set to "requiredData".

Here's the code:
/**
 * Add the Salesforce "required" appearance to an 
 * input cell.
 *
 * @param td The input cell to give a "required" 
 *           appearance.
 */
function addRequiredAppearance(td) {
    
    // Construct the wrapper div that goes inside 
    // the td.
    
    var requiredInputDiv = 
            document.createElement("div");

    requiredInputDiv.setAttribute(
            "class", "requiredInput");
    
    // Construct and append the div that renders 
    // as the red bar.
    
    var requiredBlockDiv = 
            document.createElement("div");

    requiredBlockDiv.setAttribute(
            "class", "requiredBlock");

    requiredInputDiv.appendChild(
            requiredBlockDiv);
    
    // Move each child from the td inside the 
    // wrapper div.
    
    while (td.firstChild) {
        requiredInputDiv.appendChild(
                td.removeChild(td.firstChild));
    }   // while (td.firstChild)
    
    // Append the wrapper div inside the td.
    
    td.appendChild(requiredInputDiv);
}   // function addRequiredAppearance(td)

// Iterate through every marked element to add 
// the required appearance.

jQuery(".requiredData").each(function (i) {
    addRequiredAppearance(this);
});

With the desired apex:pageBlockSectionItem elements marked, this code adds the red bar to compliment a Visualforce input element that has the required attribute set to "true".

As mentioned in the discussion thread, Salesforce may at any time change the way they render required fields. Since this was only tested in Winter '12, the hack may not work in a later release if applied as-is. However, the concept should still hold true, and as long as the function is modified appropriately all should be well.

Note: This hack uses the jQuery library for selecting marked elements.

Thursday, October 13, 2011

Trimming Whitespace in XSLT

After some digging with Google and a hit on the W3C website, it appears that the String.trim() equivalent in XSLT is normalize-space().

"XQuery 1.0 and XPath 2.0 Functions and Operators (Second Edition)." W3C.

Tuesday, May 17, 2011

Mass Deleting Picklist Values

Apparently, the only way one can (relatively) easily mass delete picklist values is by editing the object definition in the Force.com IDE.

To do this:
  1. Open the object definition (e.g., Contact.object).
  2. Delete the picklistValues elements that are no longer desired.

I had to prune a list of 485 picklist values in a language selection picklist to a more reasonable number.

Regardless of this workaround, it would be great if this feature was more easily accessible through the web UI, as per the following idea: "mass delete picklist values (setup)"


Apparently, all I succeeded in doing was shifting the order of the picklist values. At this point I am also at a loss as to how to mass delete picklist values, much to my chagrin.

However, I did eventually create a "sort of" workaround: "JavaScript Hack to Mass Delete Custom Picklist Values"

Sunday, March 20, 2011

Bug with Custom Component Rerender inside apex:repeat

I seem to have run into a bug with custom components trying to rerender parts of themselves: The rerendered component is able to display updated values as text, but formula evaluations of any updated values ignore the updated values and instead use initial values.

For example: Let's say I have a component has an apex:inputText with value="{!accountName}" that rerenders the parent apex:outputPanel during an onchange event. After rerendering, a few odd things happen:

  • The apex:inputText reverts to blank control.
  • If I display {!accountName} as text, the new value appears fine.
  • Any other components that have rendered="{!NOT(ISNULL(accountName))}" are still not rendered.

An experience is worth a million words, so I've put up a demo in my sandbox.  The source code for the demo is also available.

  1. In the Lead (standalone) section, enter something into the Name field.
  2. Click somewhere else on the page.  An Ajax refresh will occur, and the Text Insertions and Output Component Renders section should correctly update to reflect the new Name value.
  3. Now, in any Lead (from List) section, enter something into the Name field.
  4. Click somewhere else on the page.  An Ajax refresh will occur.
  5. Observe two problems:  The Name field is blanked out, and the Output Component Renders section did not change.

Hopefully, Salesforce Premier Support will tell me that the problem will be fixed immediately within the next 5 business days.  Hopefully...

Comparison of null to Integer Always Returning true

I ran across an interesting phenomenon when comparing null values to Integer values on Visualforce pages: The comparison always returns true!

  1. null < 0 evaluates to true
  2. null = 0 evaluates to true
  3. null > 0 evaluates to true

It appears that it's best not to compare null values to Integers, since the result is effectively useless.

Saturday, March 19, 2011

apex:define Tag Precedence in Visualforce Templates

I learned something interesting through trial-and-error yesterday:

If you define a set of templates where each successive template "extends" the previous template, the apex:insert tag in all previous templates are available for definition in the final implementing page.

For example, let's take take the following hierarchy of templates:
  1. SiteMasterTemplate
  2. SiteDepartmentTemplate--contains an apex:composition with template="SiteMasterTemplate"
  3. SiteProductTemplate--contains an apex:composition with template="SiteDepartmentTemplate"

Now, if we create a page called SiteSuperMotor that contains an apex:composition with template="SiteProductTemplate", our page can actually use apex:define that define apex:insert elements in SiteMasterTemplate!

Furthermore, let's say that we have apex:insert elements in both SiteDepartmentTemplate or SiteProductTemplate that share the same name attribute as an apex:insert in SiteMasterTemplate, then the SiteSuperMotor page's apex:define would only define the apex:insert in SiteMasterTemplate!

Friday, March 18, 2011

Visualforce Misinterprets Empty xmlns Attributes

For unknown reasons, Visualforce does not handle an empty xmlns attribute inside a DIV tag. Unexpected behavior will result if a DIV tag is used inside a Visualforce page with xmlns="" specified as an attribute.

If a Visualforce page that contains simple HTML is not rendering like the page from which the HTML was copied, checking for empty xmlns attributes may be the key to fixing the problem.

Monday, March 7, 2011

How to Write to a Custom Component Attribute

I spent a long time trying to figure out why the following code was not working:

<apex:component id="this" controller="MySiteInputAccountIdCtrl"
selfClosing="true">

<apex:attribute name="value" type="Id"
description="Account Id to pass back to the page."
assignTo="{!accountId}"
required="true"/>

<apex:inputText id="accountIdIText"
value="{!accountId}"/>

</apex:component>

accountId was a simple property with a vanilla pair of getter and setter methods. When the component is rendered as a component like <c:MySiteInputAccountId value="{!contact.AccountId}>, contact.AccountId would not update no matter what I typed into the input field.

Several hours later, I took a look back at a custom component that worked (and was also created by me after a similar bout of confusion)... And it turns out that I was writing the input to the wrong object. The correct component markup is as follows:

<apex:component id="this" controller="MySiteInputAccountIdCtrl"
selfClosing="true">

<apex:attribute name="value" type="Id"
description="Account Id to pass back to the page."
assignTo="{!accountId}"
required="true"/>

<apex:inputText id="accountIdIText"
value="{!value}"/>

</apex:component>

I can't believe I forgot this resolution to a 3-hour frustration almost immediately... just to experience a new 6-hour frustration on the same topic. Hopefully writing this down will help me remember my lesson and avoid a third incident.

Friday, February 25, 2011

Conversion Error setting value 'value1 value2 value3' for '#{myMultiselectPicklistValue}'.

Salesforce is great. Apex is great. Visualforce is great.

Until you run into bizarre errors with no obvious explanation, such as the following error:
Conversion Error setting value 'value1 value2 value3' for '#{myMultiselectPicklistValue}'.

This error comes from trying to save the selections from an apex:selectCheckboxes component into a multi-select picklist field. You would think that it's as easy as simply specifying {!property} for the value attribute of the apex:selectCheckboxes component. But, no, it's not.

Multi-select picklist values are stored as String values, with each option delimited with a semicolon.  This is great to know, but what happens with apex:selectCheckboxes? apex:selectCheckboxes expects a List<String>! This discussion board post hints at the annoyance awaiting developers: "Checkboxes not saving".

Basically, to spell it out for myself and for others, here's what we have to do as developers working around this problem.

What we want to write is:

<apex:selectcheckboxes value="{!mPicklistValue}">
... and in the controller ...

public String mPicklistValue { get; set; }

Instead, what we have to write is:

<apex:selectcheckboxes value="{!mPicklistValues}">
... and in the overblown controller ...
private String mPicklistValue;
public List<String> getMPicklistValues() {
    List<String> values = null;
    // Convert mPicklistValue into List of 
    // String values

    if (mPicklistValue != null)
        values = mPicklistValue.split(';');

    return values;
}   // List<String> getMPicklistValues()
public void setMPicklistValues(
        List<String> values) {

    // Convert values into a semilcolon-delimited
    // String value

    if (values == null) {
        mPicklistValue = null;
    }
    else {
        mPicklistValue = '';
        
        for (String value : values) {
            mPicklistValue += value + ';';
        }
    }
}   // void setMPicklistValues(List<String>)

Note the plural name of the custom getter and setter methods. Cheers, indeed.

Thursday, January 20, 2011

String Keys for Apex Maps Are Case-sensitive

I discovered today that String keys for Apex Maps are case-sensitive. Apparently the Strings "johndoe" and "JohnDoe" are not equal when being compared to see if the Map contains a key.

Tuesday, January 4, 2011

Deleting Characters (a.k.a. Backspacing) through SSH in PuTTY

I've been annoyed consistently by a quirk with SSH, PuTTY, Unix and sudo where pressing the backspace character prints a ^? on the terminal instead of deleting the previous character. Then, to my amazement today, I stumbled upon a way to delete characters through SSH in PuTTY without messing with any terminal configurations!

To delete characters, all one has to do is press either...
  • Shift+Backspace; or
  • Right Arrow
I assume this works with Terminal in Mac OS X or Linux as well, but I have not yet tried. Gone are the days now when I have to retype a 80+ character command just because of a single, silly typo...

Thursday, October 21, 2010

Default Status for Emails Synced through Salesforce for Outlook

The default Status value that is assigned to emails synced via Salesforce for Outlook is not the oldest Status value, but rather the first Status value on the list that marks an Activity as Completed.

For example, the Status picklist had the following options:
  1. Not Started
  2. In Progress
  3. Completed
Then, I inserted a new option before "Completed":
  1. Not Started
  2. In Progress
  3. Completed through another activity
  4. Completed
When I sync an email with Salesforce for Outlook, the email is not recorded with Status set to "Completed". Instead, the email is now logged with Status set to "Completed through another activity".

To fix this problem, all I have to do is reorder the picklist so that "Completed" comes before "Completed through another activity". There is no need to delete any picklist options and then recreate them.

Wednesday, October 20, 2010

IETF RFC 4180-compliant CSV Reader for Salesforce

After several failed attempts at creating an IETF RFC 4180-compliant CSV reader for Salesforce, I finally have a candidate of an Apex Class that may be able to fit the bill for reading a compliant CSV file and returning a nested List where the outer List contains row records, and the inner List contains the sequential values in that row.

Edit

Posting the code within a PRE tag did not work. Let's try this download link instead.

Tuesday, August 24, 2010

Passing Data between Visualforce Pages with Controllers and Extensions

I spent a fair amount of time yesterday trying to figure out how to pass information back and forth between Visualforce pages, despite finding a pretty good article in the Force.com IDE Library.

"Creating a Wizard with Visualforce Pages"
http://www.salesforce.com/us/developer/docs/cookbook/Content/vf_wizard.htm

The article got me started, but then when I moved to the actual implementation in which I wanted to use controller extensions, I would be able to pass data between pages until I started including the extensions. I was left scratching away at my head for a while.

Finally, after many trials and errors, I came to the following conclusion: In order for data to be maintained from page to page, both the controller and the extension(s) referenced must be the same across all pages in the group.

For example, assume that the following Apex classes exist:
  • MyController
  • MyPage1Ext
  • MyPage2Ext

Also assume that I am trying to pass data between the following two pages, each of which uses the functionality included in the corresponding extension:
  • MyPage1
  • MyPage2

If I specify different attributes extensions="MyPage1Ext" and extensions="MyPage2Ext" for the two pages, then I am unable to pass data back and forth even if I specify the same controller. The trick is to use the same controller and the same extensions on both pages via the attribute extensions="MyPage1Ext,MyPage2Ext".

This is a bit depressing to know, but at least now I have a framework within I can build my actual application.

Wednesday, August 18, 2010

How to Fix Backspace in SSH Session to Unix ksh Terminal

I've been annoyed for a while now by the fact that when I start an SSH session to a AIX server that uses KornShell (ksh), my backspace key no longer deletes the character immediately preceding the cursor.

Luckily, I came across a forum thread that gave a solution for this annoyance.

"KSH Terminal Settings"
http://www.unix.com/unix-dummies-questions-answers/25310-ksh-terminal-settings.html

What I found out was that I could start the SSH session and then type the command stty erase ^H, which would enable me to delete correctly both within the SSH session and in my native Mac OS X Terminal after I ended the session.

The only (possible) problem is: Now that I've changed the erase character on the server, it appears to have "stuck". So, I hope other people who are accessing the server don't suddenly find that their backspace keys have now stopped working...