Add the required indicator to your apex:inputText or apex:SelectRadio fields using jQuery

One of the frustrating aspects of salesforce is some of the UI element generation it does (and in this case, doesn’t do) for you.

While  <apex:inputField required=”true”> will add the standard salesforce required indicator (the red bar) to your page with no further effort, if you have to drop down to the lower level <apex:inputText required=”true”> tag, you’ll miss out on this help, leaving you to wrap your inputText field in various chunks of HTML in order to have Salesforce’s standard stylesheets into apply the appropriate look.

Recently I had this requirement on several text fields and a selectOption field and rather than inject lots of HTML into my VF page manually I decided to use jQuery to help me out.

First, I defined my inputText with an additional class of ‘requiredIndicator’, this is just a marker so the text field (and any others with the same class on the page) can be found by jQuery.

<apex:inputText label="{!$ObjectType.Account.fields.name.label}" required="true" styleClass="requiredIndicator"  value="{!form.AccountName}" />

Next came the jQuery (in this case I’m using a jQuery bundle I’ve previously added to the static resources)

  <apex:includeScript value="{!URLFOR($Resource.jQueryForce,'/js/jquery-1.6.4.min.js')}" />

  <script type="text/javascript">
	   $(function(){
	  		$('.requiredIndicator').wrap('<div class="requiredInput">').before('<div class="requiredBlock"></div>');
	  	}
	   );
  </script>

And here is the end result (all of these fields are inputText):

It also works with selectOptions, which also don’t show required indicators:

<apex:selectRadio value="{!stockOption}" required="true" label="Stock Availability" styleClass="requiredIndicator"> 
   <apex:selectOption itemValue="vehicleInStock" itemLabel="{!$ObjectType.PricingRequest__c.fields.VehicleInStock__c.label}"/>                    
   <apex:selectOption itemValue="dealerSwapRequired" itemLabel="{!$ObjectType.PricingRequest__c.fields.DealerSwapRequired__c.label}"/>
   <apex:selectOption itemValue="poolStock" itemLabel="{!$ObjectType.PricingRequest__c.fields.PoolStock__c.label}"/> 
   <apex:selectOption itemValue="factoryOrder" itemLabel="{!$ObjectType.PricingRequest__c.fields.FactoryOrder__c.label}"/> 
</apex:selectRadio>

Check the jQuery site to read more on class selector and the wrap and before methods

Visibility/Enablement of Buttons on page layouts should be governed by formulas

On many page layouts I often have the need to place custom buttons and often these buttons are only valid in certain contexts, for instance, one should only be able to submit the data to an external service IF the data has a status of ‘Open’.

Currently I have only four undesirable choices…

  1. Replace the page layout with a custom visualforce page
  2. Place a guard on the target of the button to tell the user “You can’t do that because of x”
  3. Change the record type of the object and then have a custom page layout for that record type.
  4. Inject Javascript into the sidebar that modifies the dom/html to hide/disable the button.
All of these options inelegant or potentially dangerous.

What I would like is the ability that when placing a button on a page layout I can define a formula field which decides if the button is visible or invisible (and enabled or disabled).

This would solve major usability issues on ALL of the force.com application development I’ve undertaken in the past 18 months.

I’ve logged this idea in the idea exchange, if you agree with it, please, please upvote it.

More Tips for the 501 Advanced Developer Exam

The exam contains a lot of ambiguous questions and things like ‘Pick which of the three below are right, Which what is NOT true’.

I remain unconvinced you can cram for it without having done a fair amount of real force.com development, normal force.com development and deployment should be something you ‘just know’ before cramming the specifics.

Topics covered

  • Custom components, syntax for declaring and usage.
  • Templating, syntax for declaring and usage.
  • Page life cycle, order of controller, action and getter/setter execution <- multiple questions.
  • isTest and its requirements for class visibility, impact on governor limits and what is valid for them to contain.
  • Things you can to do to improve test coverage.
  • Constructors, are they needed, can they be overloaded?
  • What coding constructs are valid to bind Visualforce components to (sObjects, Custom Classes and their members, Inner classes)
  • How you reference component ID’s using $Component
  • Static Resources, benefits over Documents, limits and syntax for how they are accessed
  • When to use a Full Copy sandbox, when to use a Developer Edition.
  • URL and username convention for Sandboxes (Production and DEveloper Edition vs all other types)
  • Purpose of Code Share
  • What tools can use the metadata api (Force.com IDE, Migration tool)
  • How to test inbound email handlers, what one needs to do to handle inbound email.
  • What tags are mandatory in Visualforce Email templates, when can they be used (i.e. not Mass email).
  • What package specific methods are in (System vs Test vs ApexPages vs )
  • Purposes of Governor limits (Specifically number of script lines executed)
  • How to get a Visualforce page into your solution (overriding buttons, lists in page layouts, by URL).
  • How to get / set HTTP parameters with a PageReference,  how to get a Page Reference.
  • What happens with Triggers when you merge or Undelete records, especially the CRM records (Accounts).
  • Order of trigger execution -> multiple questions from putting 6 things in the right order to nuances between ‘saving’ a record and committing a record.
  • How to recognize Dynamic SOSL, SOQL, DescribeResults and Token methods.
  • What files get created with the migration tool (package.xml, destructiveChanges.xml, files describing the object.)
  • Outbound messaging, what the contents are of its payload.
  • When you can use call outs, how triggers and callouts interact
  • Entry point for code from tests, does calling a webservice method from a test run in test or webservice context?
  • startTest and stopTest, meanings, when to use it.
  • When to use Apex and Visualforce.
  • What’s the best way to move changes between developers working together, as an ISV, or as releasing software internally.

Talend vs Apex Dataloader – Bulk upload/Download benchmarks

Key Points

  • Both Data Loader and Talend use the same underlying APIs to Salesforce and have the same options (Batch size, compression enabling/disabling, use of bulk interface)
  • There is little difference between Data Loader and Talend in overall performance
  • There is a big difference between bulk vs non bulk upload and between using and not using compression.
  • Salesforce is up to 2x faster at data retrievals than data inserts
  • One constraint that has not been quantified is the effect of limited  bandwidth on performance, it does matter, but I’m not sure how much.
Activity Tool Compression Batch size Total records Records per second Records per hour
Non bulk upload Talend No 200 5000 19 6840
Non bulk upload Talend Yes 200 5000 39 14040
Bulk upload Data Loader N/A 1000 5000 152 54720
Bulk upload Talend N/A 1000  5000 131 47160
Download Talend Yes 1000 25000 348 125280
Download Data Loader Yes 1000 25000 303 109400

Helping you pass your 501 Advanced Developer Exam

The purpose of this blog entry is to describe a contrived business problem that exercises the topics covered in the 501 Developer exam.

Problem
You are the founder and CTO of your own company, GoobleForce.com and you have, for reasons known only to yourself, concluded that there is a market for a search engine which people interact with via email.

Email Handling

  • A user from the internet will email a search query to your Developer Edition Organisation
  • You will process the incoming email, saving its subject and body to a custom object that you will create.
  • Get the users details and check whether that particular user is a Contact of the organization, if the contact is already in the system then use that contact to send the results back otherwise create a new contact.
  • When the subject and body are saved, an insert trigger (experiment with before and after) will run which conducts a search of Bing using its SOAP API.
  • You must conduct the web service call from the Trigger.
  • You will store the response into a master detail record of the search by checking whether there exist a search query similar to that in the org, if there exist then the results in the response should be merged to the existing detail record of the search.
  • Using Batch Apex and Scheduling you will then compose response emails using a Visualforce template which emails the search results back to the originating user. Also attach a PDF of the results.

Visualforce

  • Obviously people will want to use a web browser to search the web, so we’re going to develop a Visualforce page which shows the search history and when you clicks on a history, will show the search results inline. (Hint: Add an ActionSupport and ReRender)
  • Move the changes to a new custom component.
  • Add page navigation.
  • Add actionStatus to make the user aware that the data is loading.
  • It is best if you can use a custom class (not sObject) wrapper for the search results, consisting of inner and outer classes.
  • Distribute your solution across a Custom Controller, Controller Extension and a List controller
  • Make sure the page adopts the styling of the Account tab. Experiment with the effect of adding and removing the search results from the view state.

Deployment

  • Package all the changes.
  • Register a second Developer organisation.
  • Create a new, non admin user to do the extraction and importation.
  • Migrate your package between your first developer organisation and your second using only the Migration Tool.
  • Rename a key class and redeploy your solution, taking care to delete the class of the old name.

Tests

  • Write tests to exercise the ALL the above functionality, aim for over 75% coverage, including the call to the Bing web service and inbound and outbound email services.

Documentation

  • Create a sequence diagram explaining the order of execution and sequence of interactions between the controller/extensions/custom components / etc
  • Create a sequence diagram explaining the execution order of your trigger.

Teething Troubles with Winter 12?

Winter 12 hit the sandboxes this week and we were hit by one particular problem and I’ve seen two other issues pop up as well.

I haven’t confirmed the last two, but I’ve experienced the first.    Have you felt anything from the Winter 12 release?

VMForce Live Blog.

I’m putting together a ‘real’ app on VMForce + Heroku, I’m keeping an informal ‘live blog’ here :)

Maven

Maven, for some reason, failed to download ‘jdo-api-3.1′, so I manually downloaded using Chrome from here:  http://www.datanucleus.org/downloads/maven2/javax/jdo/jdo-api/3.1-SNAPSHOT-20110319/  and installed it with:

C:\Users\sherod\Documents\workspace-sts-2.5.1.RELEASE>mvn install:install-file -DgroupId=javax.jdo -DartifactId=jdo-api -Dversion=3.1-SNAPSHOT-20110319 -Dpackag
ing=jar -Dfile=C:\Users\sherod\Downloads\jdo-api-3.1-SNAPSHOT-20110319.jar

STS

If you followed the instructions and only set your FORCE_FORCEDATABASE password details at the command prompt, then that’s not going to help STS.

C:\Users\sherod\Documents\workspace-sts-2.5.1.RELEASE>set FORCE_FORCEDATABASE_URL=force://test.salesforce.com;user=steven.herod@myapp.DEV;password=PasswordJJ$eZki3gEZTUIFrOZNz9adSs

After you’ve followed the setup instructions for STS to the letter, including the use of the vFabric tc Server, you should

  1. Right click on your project
  2. Select ‘Run As, then ‘Run Configurations…’
  3. Select the VMware vFabric entry at the bottom of the list on the left, then click on its Environment tab:
  4. click Apply, then Run to run your server up with your new config.
Consider changing your persistence.xml file if you are working with an existing Schema.
Locate your persistence.xml file (src/main/resources/META-INF/) and change/add the values below in bold, lest you potentially make unintentional changes to your org.
			<property name="datanucleus.autoCreateSchema" value="false" />
			<property name="datanucleus.autoCreateWarnOnError" value="false" />
Oddities noted already
The documentation page here lists this code:
      Query q = em.createNativeQuery(soqlQuery);
        // Bind the named parameter into the query
        q.setParameter("firstName", "Bob");

But if you run it you get: “javax.persistence.PersistenceException: Bind parameters not supported on native SOQL query”.
That may be a config issue, but for now I’m hard coding parameters and will look into it further when I start to have to process user input.

Getting it going on Heroku

You are going to need Heroku set up (and git) which is kind of a big deal in and of itself, I’m not going to go into that now.

Configure your database/login details inside persistence.xml, by adding this line:


You need to follow steps 1 through 5 in this blog entry, then skip to the section labelled ‘Declare Process Types With Foreman/Procfile’. Place your Procfile in your project’s home directory and make sure the case is right (I initially created it with Notepad and it was Procfile.txt, which doesn’t work obviously.

Follow your logs in a separate command window and from the projects home directory with ‘heroku logs -t’ to keep an eye on the logs.

This is all sketchy stuff, but I’m throwing it out there, if you aren’t previously familiar with mvn, heroku, git, JPA and SpringMVC its going to be very hard going. If I have time I’ll write up a more step by step setup. But for now, onwards to functionality.

TC Server -> Not working after Heroku deployment.

Sadly, getting it running it under jetty on heroku makes it incompatible with the tomcat setup on STS, you’ll need to comment out the additions to the pom.xml including jetty, and comment out Main.java before it runs again.  I haven’t tried the ‘foreman’ inspired approach that the Heroku docs mention.  Perhaps I can get it to run under tomcat on Heroku….  I’d prefer more rapid local development than a specific preference for Tomcat.

OAuth

I’ve reverted back to my local server and I’ve jumped right into OAuth following the instructions in the documentation.  I’ve commented out the existing Security filter/filter mapping and added in the details from the documentation into web.xml like so:

<!-- Enables Spring Security -->
	<!-- <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
		</filter> -->
	<!-- <filter-mapping> <filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern> </filter-mapping> -->

	<!-- Enables Security -->
	<filter>
		<filter-name>AuthFilter</filter-name>
		<filter-class>com.force.sdk.oauth.AuthFilter</filter-class>
		<init-param>
			<param-name>connectionName</param-name>
			<param-value>forceDatabase</param-value>
		</init-param>
		<!-- Optional parameters -->
		<init-param>
			<param-name>securityContextStorageMethod</param-name>
			<param-value>cookie</param-value>
		</init-param>
		<!-- <init-param> <param-name>secure-key-file</param-name> <param-value>name
			Of Key-File</param-value> </init-param> -->
		<init-param>
			<param-name>storeUsername</param-name>
			<param-value>false</param-value>
		</init-param>

		<!-- Optional parameters for logout configuration -->
		<init-param>
			<param-name>logoutFromDatabaseDotCom</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>logoutUrl</param-name>
			<param-value>/logout</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>AuthFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

 

The most important thing to remember is if you muck up your initial config at Salesforce for OAuth (i.e. put the wrong callback URL in) you need to delete that configuration and create a new one.  Whilst it lets you edit the url it won’t actually ever work.  (As one would expect otherwise you could modify the URL after the inital setup and send calling apps somewhere bad).  Right now I’ve got a redirect happening from localhost to Salesforce, but I’m getting a ’400′ response on reply.   I’m investigating.

OAuth Continuing.

Hmm, not a 400. once I restarted everything it seems I have an infinite loop….  From localhost to SF to _auth/ back to SF….  Not sure why.  Which is a bug in the 22.0.3 version which they shipped.  According to the issue I raised here you need to use 22.0.5 or later (22.0.6 is the version I pulled and built from github).

Working with Entities.

Retrieving the records id field is mandatory in your SOQL query ([Select c.id from Custom_Object]), which is kind of logical given its the Entity ID that JPA will use.

Your classes which map to Custom objects need to drop the __c at the end, but maintain the underscore in their class name.  So ‘Criteria_Finding__c’ becomes ‘public class Criteria_Finding’

If you change your class definition, you need to get the Data Nucleus stuff to ‘do its magic’ and can’t rely on the auto-loading stuff to work.  I stop the built in tc Server, run ‘Project -> Clean..’, then start the server again.   If you just modify controllers or JSP files, you shouldn’t need to do this, just save the change and wait for the server to reload the code.