<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jeff Douglas - Technology, Coding and Bears... OH MY! &#187; Java</title>
	<atom:link href="http://blog.jeffdouglas.com/category/technology/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jeffdouglas.com</link>
	<description>Get your head out of your #@! and into the clouds!</description>
	<lastBuildDate>Thu, 02 Feb 2012 11:57:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Document Apex Code with ApexDoc</title>
		<link>http://blog.jeffdouglas.com/2011/01/27/document-apex-code-with-apexdoc/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=document-apex-code-with-apexdoc</link>
		<comments>http://blog.jeffdouglas.com/2011/01/27/document-apex-code-with-apexdoc/#comments</comments>
		<pubDate>Thu, 27 Jan 2011 15:04:46 +0000</pubDate>
		<dc:creator>Jeff Douglas</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Salesforce]]></category>

		<guid isPermaLink="false">http://blog.jeffdouglas.com/?p=3583</guid>
		<description><![CDATA[My fellow Appirian and resident super-smart guy, Aslam Bari has created a super slick tool to document Apex code. ApexDoc is essentially JavaDocs for Apex. You add comments to your source code in the JavaDoc fashion (@author, @date, @param, etc) and ApexDoc reads these and generates a nice set of HTML files that allows you [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2011%2F01%2F27%2Fdocument-apex-code-with-apexdoc%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2011%2F01%2F27%2Fdocument-apex-code-with-apexdoc%2F&amp;source=jeffdonthemic&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img style="float: left;padding-right:15px;padding-bottom:10px" title="apex_doc_logo.png" src="http://blog.jeffdouglas.com/wp-content/uploads/2011/01/apex_doc_logo.png" border="0" alt="apex_doc_logo.png" width="147" height="80" /></p>
<p>My fellow Appirian and resident super-smart guy, <a href="http://techsahre.blogspot.com/" target="_blank">Aslam Bari</a> has created a super slick tool to document Apex code. ApexDoc is essentially JavaDocs for Apex. You add comments to your source code in the JavaDoc fashion (@author, @date, @param, etc) and ApexDoc reads these and generates a nice set of HTML files that allows you to browse your class structure. <a href="http://www.aslambari.com/apexdoc.html" target="_blank">Here&#8217;s a short video</a> on the entire process.</p>
<p>Generating the ApexDocs is fairly simple. Just point to your source code, an option output file, an optional file containing the HMTL for the right Home frame (project name, description, etc) and an optional file containing author information. Sample command syntax is:</p>
<p><em>apexdoc &lt;source_directory&gt; [&lt;target_directory?&gt;] [&lt;homefile&gt;] [&lt;authorfile&gt;]</em></p>
<p><a href="http://techsahre.blogspot.com/2011/01/apexdoc-salesforce-code-documentation.html" target="_blank">Download ApexDoc here</a> along with more detailed info and feedback. </p>
<p><img title="apexdoc-screenshot.png" src="http://blog.jeffdouglas.com/wp-content/uploads/2011/01/apexdoc-screenshot.png" border="0" alt="apexdoc-screenshot.png" width="550" height="380" /></p>
<p><strong>Update</strong>: Aslam and I worked on a bug affecting Mac and Unix users. <a href="http://www.aslambari.com/apexdoc.html" target="_blank">Download the latest version</a> of the files to get the fix. Also, here are some screenshots that may help out Mac users.</p>
<p><a href="http://blog.jeffdouglas.com/wp-content/uploads/2011/01/apexdoc-filesystem.png" rel="lightbox[3583]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2011/01/apexdoc-filesystem.png" alt="" title="apexdoc-filesystem" width="500" class="alignnone size-full wp-image-3594" /></a></p>
<p><a href="http://blog.jeffdouglas.com/wp-content/uploads/2011/01/apexdoc-terminal.png" rel="lightbox[3583]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2011/01/apexdoc-terminal.png" alt="" title="apexdoc-terminal" width="500" class="alignnone size-full wp-image-3595" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jeffdouglas.com/2011/01/27/document-apex-code-with-apexdoc/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Salesforce REST API Demo from Cloudstock</title>
		<link>http://blog.jeffdouglas.com/2010/12/17/salesforce-rest-api-demo-from-cloudstock/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=salesforce-rest-api-demo-from-cloudstock</link>
		<comments>http://blog.jeffdouglas.com/2010/12/17/salesforce-rest-api-demo-from-cloudstock/#comments</comments>
		<pubDate>Fri, 17 Dec 2010 17:18:16 +0000</pubDate>
		<dc:creator>Jeff Douglas</dc:creator>
				<category><![CDATA[Code Sample]]></category>
		<category><![CDATA[Innovation]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Salesforce]]></category>

		<guid isPermaLink="false">http://blog.jeffdouglas.com/?p=3353</guid>
		<description><![CDATA[This is the demo that I put together for the Cloudstock Hackathon and I tried to throw in as many partner services as possible. I finally ended up with five so it was dubbed the &#8220;Kitchen Sink&#8221; demo. I thought some people may find it useful as it shows how to use the Force.com REST [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F12%2F17%2Fsalesforce-rest-api-demo-from-cloudstock%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F12%2F17%2Fsalesforce-rest-api-demo-from-cloudstock%2F&amp;source=jeffdonthemic&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>This is the demo that I put together for the <a href="http://www.cloudstockevent.com/cloudstockhackathon">Cloudstock Hackathon</a> and I tried to throw in as many partner services as possible. I finally ended up with five so it was dubbed the &#8220;Kitchen Sink&#8221; demo. I thought some people may find it useful as it shows how to use the Force.com REST API in conjunction with OAuth2 using the Spring MVC framework. Pat Patterson put together a great <a href="http://wiki.developerforce.com/index.php/Getting_Started_with_the_Force.com_REST_API">Getting Started with the Force.com REST API article</a> but my app is slightly different and IMHO easier, since it uses the Spring Framework.</p>
<p>The app is a external-facing recruiting site that advertises the open <a href="http://www.appirio.com/careers">Appirio positions</a>. Please remember that this is a demo and I put most of the code into a couple of controllers to make it easier to show. The code can definitely be refactored in certain places. </p>
<p>Here&#8217;s how the app uses the partner services:</p>
<p><table width="100%">
<tr>
<th>Partner</th>
<th>How Used?</th>
</tr>
<tr>
<td><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/Box.png" rel="lightbox[3353]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/Box.png" alt="" title="Box" width="96" height="48" class="alignnone size-full wp-image-3365" /></a></td>
<td>Store pdf job descriptions on Box for download by applicants.</td>
</tr>
<tr>
<td><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/Force.png" rel="lightbox[3353]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/Force.png" alt="" title="Force.com" width="200" height="57" class="alignnone size-full wp-image-3363" /></a></td>
<td>Use Force.com as the datastore for open jobs. Access to Force.com using OAuth2 and the REST API.</td>
</tr>
<tr>
<td><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/Twilio.png" rel="lightbox[3353]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/Twilio.png" alt="" title="Twilio" width="180" height="60" class="alignnone size-full wp-image-3368" /></a></td>
<td>Send a job to a friend via SMS.</td>
</tr>
<tr>
<td><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/VMWare.png" rel="lightbox[3353]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/VMWare.png" alt="" title="VMWare" width="180" height="28" class="alignnone size-full wp-image-3369" /></a></td>
<td>Application built using Spring STS, Spring Roo and Spring MVC. The application runs locally on tc Server.</td>
</tr>
<tr>
<td><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/MongoDB.png" rel="lightbox[3353]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/MongoDB.png" alt="" title="MongoDB" width="149" height="48" class="alignnone size-full wp-image-3367" /></a></td>
<td>Store metrics for jobs on MongoHQ.</td>
</tr>
</table>
<p>Here&#8217;s a video of the application so you can see it in action plus some explanation of the Spring code. The controller code for the OAuth functionality and interacting with the Job records is following the jump.</p>
<p><em>It may be easier to watch this at Youtube with a larger picture. Just double-click the video.</em></p>
<p><span class="youtube">
<object width="560" height="340">
<param name="movie" value="http://www.youtube.com/v/TFNJaHYEK3U?color1=d6d6d6&amp;color2=f0f0f0&amp;border=0&amp;fs=1&amp;hl=en&amp;loop=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0&amp;rel=1&amp;hd=1&#038;hd=1&#038;w=550" />
<param name="allowFullScreen" value="true" />
<embed wmode="opaque" src="http://www.youtube.com/v/TFNJaHYEK3U?color1=d6d6d6&amp;color2=f0f0f0&amp;border=0&amp;fs=1&amp;hl=en&amp;loop=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0&amp;rel=1&amp;hd=1&#038;hd=1&#038;w=550" type="application/x-shockwave-flash" allowfullscreen="true" width="560" height="340"></embed>
<param name="wmode" value="opaque" />
</object>
</span><p><a href="http://www.youtube.com/watch?v=TFNJaHYEK3U&fmt=18">www.youtube.com/watch?v=TFNJaHYEK3U</a></p></p>
<p><strong>OAuthController</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">package com.appirio.jobs.web;
&nbsp;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
&nbsp;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.WebRequest;
&nbsp;
/**
 * @author Jeff Douglas (jeff@appirio.com)
 */
@RequestMapping(&quot;/oauth/**&quot;)
@Controller
public class OAuthController {
&nbsp;
  private static final String ACCESS_TOKEN = &quot;ACCESS_TOKEN&quot;;
  private static final String INSTANCE_URL = &quot;INSTANCE_URL&quot;;
&nbsp;
  private String clientId = null;
  private String clientSecret = null;
  private String redirectUri = null;
  private String environment = null;
  private String authUrl = null;
  private String tokenUrl = null;
  private String accessToken = null;
&nbsp;
  private void init() {
&nbsp;
      redirectUri = &quot;https://127.0.0.1:8443/AppirioCareers/oauth/_callback&quot;;
      environment = &quot;https://na5.salesforce.com&quot;;
      // client id and secret from Force.com Remote Access
      clientId = &quot;YOUR-CLIENT-ID&quot;;
      clientSecret = &quot;YOUR-CLIENT-SECRET&quot;;
&nbsp;
        try {
      authUrl = environment + &quot;/services/oauth2/authorize?response_type=code&amp;client_id=&quot; 
        + clientId + &quot;&amp;redirect_uri=&quot; + URLEncoder.encode(redirectUri, &quot;UTF-8&quot;);
    } catch (UnsupportedEncodingException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    }
&nbsp;
        tokenUrl = environment + &quot;/services/oauth2/token&quot;;
&nbsp;
  }
&nbsp;
  /* Start the OAuth process if no session with the access token is found. 
   * If a session exists, the redirect the user to the /job/list page. */
  @RequestMapping(value = &quot;/oauth/start&quot;, method = RequestMethod.GET)
  public String startOauth(WebRequest req) {
&nbsp;
    init();
    // check for an access token in the servlet session
    accessToken = (String) req.getAttribute(ACCESS_TOKEN, RequestAttributes.SCOPE_SESSION);
&nbsp;
    if (accessToken != null) {
      System.out.println(&quot;Session found!! Access token: &quot;+accessToken);
      return &quot;forward:/job/list&quot;;
    } else {
      System.out.println(&quot;No session... need to auth.&quot;);        
      return &quot;redirect:&quot; + authUrl;
    }
&nbsp;
  }
&nbsp;
  /* OAuth callback from Force.com after authrozing the application.  */
  @RequestMapping(value = &quot;/oauth/_callback&quot;, method = RequestMethod.GET)
  public String endOauth(WebRequest req) {
&nbsp;
    init();
    String accessToken = null;
    String instanceUrl = null;
    String code = req.getParameter(&quot;code&quot;);
    HttpClient http = new HttpClient();
    PostMethod post = new PostMethod(tokenUrl);
    post.addParameter(&quot;client_secret&quot;, clientSecret);
    post.addParameter(&quot;redirect_uri&quot;, redirectUri);
    post.addParameter(&quot;grant_type&quot;, &quot;authorization_code&quot;);
    post.addParameter(&quot;code&quot;, code);
    post.addParameter(&quot;client_id&quot;, clientId);
&nbsp;
    try {
      JSONObject json = null;
      http.executeMethod(post);
      String respBody = post.getResponseBodyAsString();
      System.out.println(&quot;post response: &quot; + respBody);
      try {
        json = new JSONObject(respBody);
        accessToken = json.getString(&quot;access_token&quot;);
        instanceUrl = json.getString(&quot;instance_url&quot;);
      } catch (JSONException e) {
        e.printStackTrace();
      }
      System.out.println(&quot;found access token: &quot;+accessToken);
      System.out.println(&quot;found instance url: &quot;+instanceUrl);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } finally {
      post.releaseConnection();
    }
&nbsp;
    System.out.println(&quot;Setting Access token: &quot;+accessToken);
    System.out.println(&quot;Setting Instance Url: &quot;+instanceUrl);
&nbsp;
    /* Set the token and url to the session so other servlets can access it. */
    req.setAttribute(ACCESS_TOKEN, accessToken, RequestAttributes.SCOPE_SESSION);
    req.setAttribute(INSTANCE_URL, instanceUrl, RequestAttributes.SCOPE_SESSION);
&nbsp;
    return &quot;forward:/job/list&quot;;
  }
&nbsp;
  @RequestMapping
  public String index() {
    return &quot;oauth/index&quot;;
  }
}</pre></td></tr></table></div>

<p><strong>JobController</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">package com.appirio.jobs.web;
&nbsp;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
&nbsp;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod; 
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;
&nbsp;
import com.appirio.jobs.domain.Job;
import com.appirio.jobs.domain.SmsMessage;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestException;
import com.twilio.sdk.TwilioRestResponse;
&nbsp;
/**
 * @author Jeff Douglas (jeff@appirio.com)
 */
&nbsp;
@RequestMapping(&quot;/job/**&quot;)
@Controller
public class JobController {
&nbsp;
  private static final String ACCESS_TOKEN = &quot;ACCESS_TOKEN&quot;;
  private static final String INSTANCE_URL = &quot;INSTANCE_URL&quot;;
  private static Mongo m;
  private static DB db;
  private static DBCollection coll;
  private static DBCursor cur;
  private ArrayList&lt;Job&gt; jobs = new ArrayList&lt;Job&gt;();
&nbsp;
&nbsp;
    @RequestMapping(value=&quot;/job/list&quot;, method=RequestMethod.GET)
    public ModelAndView list(WebRequest req) {
&nbsp;
      // if the job collection is empty then fetch jobs from Force.com
      if (jobs.isEmpty()) {
&nbsp;
        // fetch the access token and url from the servlet session
        String accessToken = (String) req.getAttribute(ACCESS_TOKEN, RequestAttributes.SCOPE_SESSION);
        String instanceUrl = (String) req.getAttribute(INSTANCE_URL, RequestAttributes.SCOPE_SESSION);
&nbsp;
        System.out.println(&quot;Access token: &quot;+accessToken);
        System.out.println(&quot;Instance Url: &quot;+instanceUrl);
&nbsp;
        jobs = new ArrayList&lt;Job&gt;();
      HttpClient httpclient = new HttpClient();
          GetMethod gm = new GetMethod(instanceUrl + &quot;/services/data/v20.0/query&quot;);
          //set the token in the header
          gm.setRequestHeader(&quot;Authorization&quot;, &quot;OAuth &quot;+accessToken);
          //set the SOQL as a query param
          NameValuePair[] params = new NameValuePair[1];
          //no need to url encode here...it will cause your query to fail
          params[0] = new NameValuePair(&quot;q&quot;,&quot;Select Id, Name, Job_Title__c, Location__c, &quot; +
              &quot;Duties__c, Skills__c, Salary__c, Box_Url__c from Job__c Order by Job_Title__c&quot;);
          gm.setQueryString(params);
&nbsp;
          String respBody = &quot;&quot;;
&nbsp;
          try {
        httpclient.executeMethod(gm);
        respBody = gm.getResponseBodyAsString();
            System.out.println(&quot;response body: &quot; + respBody);
      } catch (HttpException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
      } catch (IOException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
      } finally {
              gm.releaseConnection();
          }
&nbsp;
          try {
              JSONObject json = new JSONObject(respBody);                
              JSONArray results = json.getJSONArray(&quot;records&quot;);
&nbsp;
             for(int i = 0; i &lt; results.length(); i++) {
               // add the json payload to a Job object
               Job job = new Job(results.getJSONObject(i).getString(&quot;Id&quot;), 
            results.getJSONObject(i).getString(&quot;Name&quot;),
            results.getJSONObject(i).getString(&quot;Job_Title__c&quot;),
            results.getJSONObject(i).getString(&quot;Location__c&quot;),
            results.getJSONObject(i).getString(&quot;Duties__c&quot;),
            results.getJSONObject(i).getString(&quot;Skills__c&quot;),
            results.getJSONObject(i).getString(&quot;Salary__c&quot;),
            results.getJSONObject(i).getString(&quot;Box_Url__c&quot;));
&nbsp;
               // add the job to the collection
               jobs.add(job);
             }
&nbsp;
&nbsp;
          } catch (JSONException e) {
              e.printStackTrace();
          }
&nbsp;
          System.out.println(&quot;jobs found: &quot;+jobs.size());
&nbsp;
      }
&nbsp;
      ModelAndView mav = new ModelAndView(&quot;job/list&quot;);
      mav.addObject(&quot;jobs&quot;, jobs);
      return mav;
    }
&nbsp;
    @RequestMapping(value=&quot;/job/{id}/display&quot;, method=RequestMethod.GET)
    public ModelAndView display(@PathVariable String id, Model model) {
      Job job = getJobById(id);
      incrementCount(job.getName(),&quot;views&quot;);
      ModelAndView mav = new ModelAndView(&quot;job/display&quot;);
      mav.addObject(getJobById(id));
      return mav;
    }
&nbsp;
    @RequestMapping(value=&quot;/job/{id}/sms&quot;, method=RequestMethod.GET)
    public ModelAndView message(@PathVariable String id, Model model) {
      ModelAndView mav = new ModelAndView(&quot;job/sms&quot;); 
      SmsMessage sms = new SmsMessage();
      sms.setPhone(&quot;9412274843&quot;);
      sms.setMessage(&quot;Check out this AWESOME job with Appirio!&quot;);
      mav.addObject(&quot;smsMessage&quot;, sms);
      mav.addObject(getJobById(id));
      return mav;
    }
&nbsp;
    @RequestMapping(value=&quot;/job/{id}/print&quot;, method=RequestMethod.GET)
    public String print(@PathVariable String id, Model model) {
      Job job = getJobById(id);
      incrementCount(job.getName(),&quot;downloads&quot;);
      System.out.println(job.getBoxUrl());
      return &quot;redirect:&quot;+job.getBoxUrl();
    }
&nbsp;
    @RequestMapping(value = &quot;/job/{id}/smsSend&quot;, method = RequestMethod.POST)
    public ModelAndView smsSubmit(@PathVariable String id, @ModelAttribute SmsMessage sms, Model model) {
&nbsp;
      Job job = getJobById(id);
      sendSms(job, sms.getPhone(), sms.getMessage());
      incrementCount(job.getName(),&quot;messages&quot;);
&nbsp;
      ModelAndView mav = new ModelAndView(&quot;job/smsConfirm&quot;); 
      mav.addObject(&quot;phone&quot;, sms.getPhone());
      mav.addObject(&quot;message&quot;, sms.getMessage());
      mav.addObject(job);
      return mav;
&nbsp;
    }
&nbsp;
  private void incrementCount(String name, String type) {
&nbsp;
    try {
      m = new Mongo(&quot;flame.mongohq.com&quot;, 27065);
      db = m.getDB(&quot;AppirioCareers&quot;);
      char[] password = { '4','+','r','E','o','x','x','x','x','x'};
      boolean auth = db.authenticate(&quot;jeffdonthemic&quot;, password);
      System.out.println(&quot;Mongo auth?: &quot;+auth);
      coll = db.getCollection(&quot;jobs&quot;);  
    }
    catch (UnknownHostException ex) {
      ex.printStackTrace();
    }
    catch (MongoException ex) {
      ex.printStackTrace();
    }
&nbsp;
    cur = coll.find(new BasicDBObject(&quot;name&quot;, name));  
    while (cur.hasNext()) {
      BasicDBObject doc = (BasicDBObject)cur.next();
      if (type.equals(&quot;views&quot;))
        doc.put(&quot;views&quot;, (Integer)doc.get(&quot;views&quot;)+1);
      else if (type.equals(&quot;messages&quot;))
        doc.put(&quot;messages&quot;, (Integer)doc.get(&quot;messages&quot;)+1);
      else
        doc.put(&quot;downloads&quot;, (Integer)doc.get(&quot;downloads&quot;)+1);
      coll.update( new BasicDBObject(&quot;name&quot;, name), doc );
    }
&nbsp;
  }
&nbsp;
    private void sendSms(Job job, String phone, String message) {
&nbsp;
        String AccountSid = &quot;YOUR-ACCOUNT-ID&quot;;
        String AuthToken = &quot;YOUR-AUTH-TOKEN&quot;;
        String ApiVersion = &quot;2010-04-01&quot;;
&nbsp;
        TwilioRestClient client = new TwilioRestClient(AccountSid, AuthToken, null);
&nbsp;
        String msg = &quot;\n&quot;+message+&quot;\n&quot;+job.getJobTitle()+&quot;\nhttp://appirio.com/careers&quot;;
&nbsp;
        System.out.println(&quot;size: &quot;+msg.length());
&nbsp;
        //build map of post parameters 
        Map&lt;String,String&gt; params = new HashMap&lt;String,String&gt;();
        params.put(&quot;From&quot;, &quot;14155992671&quot;);
        params.put(&quot;To&quot;, phone);
        params.put(&quot;Body&quot;, msg);
        TwilioRestResponse response;
        try {
            response = client.request(&quot;/&quot;+ApiVersion+&quot;/Accounts/&quot;+AccountSid+&quot;/SMS/Messages&quot;, &quot;POST&quot;, params);
&nbsp;
            if(response.isError())
                System.out.println(&quot;Error making outgoing call: &quot;+response.getHttpStatus()+&quot;\n&quot;+response.getResponseText());
            else {
                System.out.println(response.getResponseText());
&nbsp;
            }
        } catch (TwilioRestException e) {
            e.printStackTrace();
        }
&nbsp;
    }
&nbsp;
    private Job getJobById(String id) {
      Job job = null;
      for (Job j : jobs) {
        if (j.getId().equals(id)) {
          job = j;
          break;
        }
      }
      return job;
    }
&nbsp;
    @RequestMapping
    public String index() {
        return &quot;job/index&quot;;
    }
&nbsp;
}</pre></td></tr></table></div>

<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jeffdouglas.com/2010/12/17/salesforce-rest-api-demo-from-cloudstock/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>My VMforce and Facebook Demos Today at Dreamforce</title>
		<link>http://blog.jeffdouglas.com/2010/12/08/my-vmforce-and-facebook-demos-today-at-dreamforce/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=my-vmforce-and-facebook-demos-today-at-dreamforce</link>
		<comments>http://blog.jeffdouglas.com/2010/12/08/my-vmforce-and-facebook-demos-today-at-dreamforce/#comments</comments>
		<pubDate>Wed, 08 Dec 2010 15:28:40 +0000</pubDate>
		<dc:creator>Jeff Douglas</dc:creator>
				<category><![CDATA[Appirio]]></category>
		<category><![CDATA[Innovation]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[VMforce]]></category>

		<guid isPermaLink="false">http://blog.jeffdouglas.com/?p=3333</guid>
		<description><![CDATA[If you are at Dreamforce today here are the sessions that I am speaking in. I&#8217;m really excited to be part of both of them as the topics (VMforce and the new Facebook toolkit) are really cool. Leveraging Public Social Networks &#8211; West 2005 @ 12:15 We&#8217;ll be showing off the new Facebook toolkit and [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F12%2F08%2Fmy-vmforce-and-facebook-demos-today-at-dreamforce%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F12%2F08%2Fmy-vmforce-and-facebook-demos-today-at-dreamforce%2F&amp;source=jeffdonthemic&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>If you are at Dreamforce today here are the sessions that I am speaking in. I&#8217;m really excited to be part of both of them as the topics (VMforce and the new Facebook toolkit) are really cool.</p>
<p>
<h3>Leveraging Public Social Networks &#8211; West 2005 @ 12:15</h3>
</p>
<p>We&#8217;ll be showing off the new Facebook toolkit and building a few applications.</p>
<p><img title="df10-facebook.png" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/df10-facebook.png" border="0" alt="df10-facebook.png" width="525" height="331" /></p>
<p><br/><br/></p>
<p>
<h3>VMforce: The Trusted Enterprise Platform as a Service - Force.com Theater @ 1:45</h3>
</p>
<p>I&#8217;ll be demoing an app built using Spring STS, Spring Roo and Spring MVC connecting to the Force.com Database using JPA and running on the VMforce servers. I&#8217;ll show you the code, pick it apart and talk about best practices.</p>
<p><img title="df10-vmforce.png" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/12/df10-vmforce.png" border="0" alt="df10-vmforce.png" width="525" height="366" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jeffdouglas.com/2010/12/08/my-vmforce-and-facebook-demos-today-at-dreamforce/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cloud Computing for Java Developers Webinar (VMforce)</title>
		<link>http://blog.jeffdouglas.com/2010/09/10/cloud-computing-for-java-developers-webinar-vmforce/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=cloud-computing-for-java-developers-webinar-vmforce</link>
		<comments>http://blog.jeffdouglas.com/2010/09/10/cloud-computing-for-java-developers-webinar-vmforce/#comments</comments>
		<pubDate>Fri, 10 Sep 2010 09:46:00 +0000</pubDate>
		<dc:creator>Jeff Douglas</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[VMforce]]></category>

		<guid isPermaLink="false">http://blog.jeffdouglas.com/?p=3237</guid>
		<description><![CDATA[I attended the Cloud Computing for Java Developers webinar yesterday, which was essentially an intro to VMforce and the Force.com platform for (non-Force.com) Java developers. Quinton Wall and Jesper Joergensen did a good job with the overview of the platform but I was really looking for some tidbits on VMforce. You can watch the recording [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F09%2F10%2Fcloud-computing-for-java-developers-webinar-vmforce%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F09%2F10%2Fcloud-computing-for-java-developers-webinar-vmforce%2F&amp;source=jeffdonthemic&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>I attended the <strong>Cloud Computing for Java Developers</strong> webinar yesterday, which was essentially an intro to VMforce and the Force.com platform for (non-Force.com) Java developers. Quinton Wall and Jesper Joergensen did a good job with the overview of the platform but I was really looking for some tidbits on VMforce. You can watch the <a href="http://wiki.developerforce.com/index.php/VMforce_Webinar_Series">recording of the webinar</a> but here are some things that I found interesting&#8230;</p>
<p>1. For accessing the Force.com Database, developers will be able to use <a href="http://en.wikipedia.org/wiki/Java_Persistence_API">JPA</a>, the new REST API and the <a href="http://code.google.com/p/sfdc-wsc/">Force.com WSC</a> (SOAP-based).</p>
<p>2. According  to Jesper, VMforce will not be included for all orgs. It will be an  additional cost possibly as an additional license or subscription.  However, it will be available to developers in DE orgs.</p>
<p>3. The Force.com IDE installs on top of <a href="http://www.springsource.com/developer/sts">SpringSouce Tool Suite</a> (Eclipse)</p>
<p>4. Quinton provided a little more info on the REST API that will be piloted starting Winter 11.</p>
<p><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/09/vmforce-webinar6.png" rel="lightbox[3237]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/09/vmforce-webinar6-1024x699.png" alt="" title="vmforce-webinar6" width="525" class="alignnone size-large wp-image-3243" /></a></p>
<p>5. VMforce apps are built, tested and debugged locally and then deployed to the Force.com tcServer instance as easily as any other web application would be deployed on-premise. To the IDE, Force.com just looks like another server.</p>
<p><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/09/vmforce-webinar4.png" rel="lightbox[3237]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/09/vmforce-webinar4-1024x699.png" alt="" title="vmforce-webinar4" width="525" class="alignnone size-large wp-image-3241" /></a></p>
<p>6. Quinton did a quick demo where he created a simple POJO, deployed it to the server and it automatically created a Custom Object for it in Force.com (this auto-generation will probably be configurable in the future). VMforce is using the JPA implementation from <a href="http://www.datanucleus.org/">DataNucleus</a> (same as App Engine). Quinton&#8217;s provided some code examples where he queried Contact records using JPA and then displayed them in the browser:</p>
<p><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/09/vmforce-webinar7.png" rel="lightbox[3237]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/09/vmforce-webinar7-1024x699.png" alt="" title="vmforce-webinar7" width="525 class="alignnone size-large wp-image-3244" /></a></p>
<p><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/09/vmforce-webinar8.png" rel="lightbox[3237]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/09/vmforce-webinar8-1024x699.png" alt="" title="vmforce-webinar8" width="525" class="alignnone size-large wp-image-3245" /></a></p>
<p>The summary slide wrapped up the webinar.</p>
<p><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/09/vmforce-webinar11.png" rel="lightbox[3237]"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/09/vmforce-webinar11-1024x699.png" alt="" title="vmforce-webinar11" width="525" class="alignnone size-large wp-image-3246" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jeffdouglas.com/2010/09/10/cloud-computing-for-java-developers-webinar-vmforce/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Error Compiling Salesforce Metadata API with WSC</title>
		<link>http://blog.jeffdouglas.com/2010/07/01/error-compiling-salesforce-metadata-api-with-wsc/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=error-compiling-salesforce-metadata-api-with-wsc</link>
		<comments>http://blog.jeffdouglas.com/2010/07/01/error-compiling-salesforce-metadata-api-with-wsc/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 12:00:52 +0000</pubDate>
		<dc:creator>Jeff Douglas</dc:creator>
				<category><![CDATA[Code Sample]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Salesforce]]></category>

		<guid isPermaLink="false">http://blog.jeffdouglas.com/2010/07/01/error-compiling-salesforce-metadata-api-with-wsc/</guid>
		<description><![CDATA[This might not be relevant right now but you may find it useful in the near future. I&#8217;m tinkering with an app that spits out documentation for an org. I really hate doing documentation and am quite lazy so I thought I&#8217;d write something to allow my computer to do my work for me. I [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F07%2F01%2Ferror-compiling-salesforce-metadata-api-with-wsc%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F07%2F01%2Ferror-compiling-salesforce-metadata-api-with-wsc%2F&amp;source=jeffdonthemic&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p style="clear: both">This might not be relevant right now but you may find it useful in the near future. I&#8217;m tinkering with an app that spits out documentation for an org. I really hate doing documentation and am quite lazy so I thought I&#8217;d write something to allow my computer to do my work for me. </p>
<p style="clear: both">I ran into a small issue when trying to compile the Metadata WSDL with the <a href="http://code.google.com/p/sfdc-wsc/" target="_blank">Force.com Web Services Connector</a> so I thought I&#8217;d post my fix.</p>
<p style="clear: both">So to use the Metadata API with the WSC, first download the Metadata WSDL from your org and the latest <a href="http://code.google.com/p/sfdc-wsc/downloads/list" target="_blank">WSC jar from the project</a>. Now issue something like the following to generate the stub code from the WSDL:</p>
<blockquote style="clear: both"><p style="clear: both">java -classpath wsc-19.jar com.sforce.ws.tools.wsdlc metadata.wsdl metadata.jar</p>
</blockquote>
<p style="clear: both">Unfortunately this results in an error similar to:</p>
<blockquote style="clear: both"><p style="clear: both">-dir/com/sforce/soap/metadata/Encoding.java:12: &#8216;} &#8216; expected UTF-8,</p>
</blockquote>
<p style="clear: both"><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/07/terminal-error.png" class="image-link" rel="lightbox[2747]"><img class="linked-to-original" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/07/terminal-error-thumb.png" height="275" align="left" width="380" style=" display: inline; float: left; margin: 0 10px 10px 0;" /></a><br style="clear: both" />The error is thrown because the WSDL contains some hyphens that is making the compiler puke. <strong>You can fix the issue by replacing the hyphens in the Metadata WSDL with underscores</strong>, saving the WSDL and then compiling the stub code again. </p>
<p style="clear: both">Here&#8217;s the offending portion of the Metadata WSDL.</p>
<p style="clear: both"><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/07/metadataapi-replace.png" class="image-link" rel="lightbox[2747]"><img class="linked-to-original" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/07/metadataapi-replace-thumb.png" height="239" align="left" width="332" style=" display: inline; float: left; margin: 0 10px 10px 0;" /></a></p>
<p><br class="final-break" style="clear: both" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jeffdouglas.com/2010/07/01/error-compiling-salesforce-metadata-api-with-wsc/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Get Ready for VMForce &#8211; Here&#8217;s How!</title>
		<link>http://blog.jeffdouglas.com/2010/06/29/get-ready-for-vmforce/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=get-ready-for-vmforce</link>
		<comments>http://blog.jeffdouglas.com/2010/06/29/get-ready-for-vmforce/#comments</comments>
		<pubDate>Tue, 29 Jun 2010 14:59:41 +0000</pubDate>
		<dc:creator>Jeff Douglas</dc:creator>
				<category><![CDATA[Cloud Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[VMforce]]></category>

		<guid isPermaLink="false">http://blog.jeffdouglas.com/?p=2730</guid>
		<description><![CDATA[VMForce is coming (sometime in the near future) so what can you do to get started now? If I was a betting man (with inside info), here is what I&#8217;d do to get ready. Start Building on Google App EngineMy guess is that VMForce will look a little like Google App Engine. You&#8217;ll probably have [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F06%2F29%2Fget-ready-for-vmforce%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F06%2F29%2Fget-ready-for-vmforce%2F&amp;source=jeffdonthemic&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p style="clear: both"><a href="http://www.vmforce.com/"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/06/vmforce.png" alt="" title="vmforce" width="223" height="92" class="alignleft size-full wp-image-2731" /></a><a href="http://www.vmforce.com/" target="_blank">VMForce</a> is coming (sometime in the near future) so what can you do to get started now? If I was a betting man (with inside info), here is what I&#8217;d do to get ready. </p>
<p style="clear: both"><strong>Start Building on Google App Engine</strong><br />My guess is that VMForce will look a little like Google App Engine. You&#8217;ll probably have access to a wide range of Java libaries but not all of them. Based upon Salesforce.com&#8217;s current model you can expect that there will be some platform governors and limits in place. This should provide you with some experience and a working knowledge of some issues you may run into. If you want to get up and running quickly you can always buy my book <a href="http://www.amazon.com/gp/product/143022553X?ie=UTF8&#038;tag=jefdoublo-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=143022553X" target="_blank">Beginning Java Google App Engine</a> (yes&#8230; blatant plug).</p>
<p style="clear: both"><strong>Start Learning Spring</strong><br />I would probably start with Spring MVC or <a href="http://www.springsource.org/webflow" target="_blank">Spring Web Flow 2</a> initially. The good thing is that most of Spring also runs on App Engine so you <em>should</em> be able to move any apps you write on App Engine to VMForce. Here&#8217;s a <a href="http://static.springsource.org/docs/Spring-MVC-step-by-step" target="_blank">great article</a> to get you started with Spring MVC.</p>
<p style="clear: both">I would also download the <a href="http://www.springsource.com/products/sts" target="_blank">SpringSource Tool Suite</a> which is a Eclipse plugin for Spring development. It should fit in nicely with the Force.com IDE.</p>
<p style="clear: both">You might also want to dowload Spring&#8217;s <a href="http://www.springsource.com/products/tcserver" target="_blank">tc Server Developer Edition</a>. If you are using App Engine you can develop locally but you might also want to check out tc Server. The key component of tc Server Developer Edition is the Spring Insight console, a dashboard view of real-time Spring application performance metrics. Without changing code, developers can use Spring Insight to detect, analyze and diagnose application performance issues right from the desktops. This was demoed at Google IO and it was very slick! There&#8217;s a <a href="http://s3.springsource.com/MRKT/spring-metrics/Spring_Insight-Milestone_3-Screencast.mp4" target="_blank">really cool video</a> if you want to see how it works.</p>
<p style="clear: both"><strong>Dig into Persistence Layers</strong><br />You&#8217;ll definitely want to start working with a persistance layer like JDO, JPA or Hibernate. Based upon some <a href="http://blog.sforce.com/sforce/2010/06/forcecom-for-java-developers.html" target="_blank">recent comments</a> from Salesforce.com, I would look at JPA first.</p>
<p style="clear: both"><strong>Develop with the Force.com Web Service Connector (WSC)</strong><br />Most developers are familiar with the WS-APIs but you should really start looking at the <a href="ttp://code.google.com/p/sfdc-wsc" target="_blank">Force.com Web Service Connector</a>. I&#8217;m writing an article for developer.force.com on how to use the WSC so keep an eye out for that shortly.</p>
<p style="clear: both"><strong>Try Spring Roo</strong><br />If you have some extra time you might want to look into <a href="http://www.springsource.org/roo/why" target="_blank">Spring Roo</a>. Roo is a lightweight developer tool that allows you to build apps in minutes. They demoed Roo and Google Web Toolkit together at Google IO with impressive results.</p>
<p><br class="final-break" style="clear: both" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jeffdouglas.com/2010/06/29/get-ready-for-vmforce/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
<enclosure url="http://s3.springsource.com/MRKT/spring-metrics/Spring_Insight-Milestone_3-Screencast.mp4" length="82795161" type="video/mp4" />
		</item>
		<item>
		<title>Salesforce Chatter for Android</title>
		<link>http://blog.jeffdouglas.com/2010/06/06/salesforce-chatter-for-android/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=salesforce-chatter-for-android</link>
		<comments>http://blog.jeffdouglas.com/2010/06/06/salesforce-chatter-for-android/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 15:25:23 +0000</pubDate>
		<dc:creator>Jeff Douglas</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Cloud Computing]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.jeffdouglas.com/?p=2628</guid>
		<description><![CDATA[My blog has been a little quiet since I left for Google IO a few weeks ago and this is primarily the reason why. In addition to my day job I&#8217;ve been working on getting up-to-speed on Android development. Google sent me a Droid about a month before the conference and I started playing around [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F06%2F06%2Fsalesforce-chatter-for-android%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F06%2F06%2Fsalesforce-chatter-for-android%2F&amp;source=jeffdonthemic&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p style="clear: both"><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/06/chatter-android.png" class="image-link" rel="lightbox[2628]"><img class="linked-to-original" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/06/chatter-android-thumb.png" height="195" align="left" width="175" style=" display: inline; float: left; margin: 0 10px 10px 0;" /></a>My blog has been a little quiet since I left for <a href="http://www.youtube.com/user/GoogleDevelopers#p/a" target="_blank">Google IO</a> a few weeks ago and this is primarily the reason why. In addition to my day job I&#8217;ve been working on getting up-to-speed on Android development. Google sent me a Droid about a month before the conference and I started playing around with some tutorials and writing a few apps before IO (smart idea to send out 5K Droids to spur development). I really caught the Android bug at the event and thought that the <a href="http://developer.force.com/chatter_developer_challenge" target="_blank">Chatter Developer Challenge</a> would be a great way to kill two birds with the proverbial one stone. </p>
<p style="clear: both">So here is the demo of the application that I just submitted for the Chatter Developer Challenge. It is a Salesforce Chatter for Android app running on a combination of the <a href="http://www.salesforce.com/platform/" target="_blank">Force.com platform</a>, <a href="http://code.google.com/appengine/" target="_blank">Google App Engine</a> and a <a href="http://www.android.com/" target="_blank">Google Android</a> mobile handset. It utilizes F<a href="http://developer.force.com/releases/release_feature?key=Remote+Access+Applications+with+OAuth" target="_blank">orce.com Remote Access Applications</a> with <a href="http://hueniverse.com/oauth/guide/terminology/" target="_blank">3-legged OAuth</a> for security. The Android application has the following functionality:</p>
<ul style="clear: both">
<li>Display your Chatter NewsFeed</li>
<li>Update your User status</li>
<li>Refresh your Chatter NewsFeed and store it in the local SQLite database</li>
<li>Choose a project (custom object) that you are following and view its Chatter Feed</li>
<li>Update the project&#8217;s status</li>
<li>Refresh the Chatter Feed for the project (including field changes to the record) and store it in the local SQLite database</li>
</ul>
<p style="clear: both">The app does not include the functionality to reply to posts. Since Chatter is running in a Developer Edition and they are only allowed to have 1 user, it seemed rather pointless to respond to my own posts. </p>
<p><span class="youtube">
<object width="560" height="340">
<param name="movie" value="http://www.youtube.com/v/2KggRjco6bs?color1=d6d6d6&amp;color2=f0f0f0&amp;border=0&amp;fs=1&amp;hl=en&amp;loop=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0&amp;rel=1&amp;hd=1&#038;w=550" />
<param name="allowFullScreen" value="true" />
<embed wmode="opaque" src="http://www.youtube.com/v/2KggRjco6bs?color1=d6d6d6&amp;color2=f0f0f0&amp;border=0&amp;fs=1&amp;hl=en&amp;loop=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0&amp;rel=1&amp;hd=1&#038;w=550" type="application/x-shockwave-flash" allowfullscreen="true" width="560" height="340"></embed>
<param name="wmode" value="opaque" />
</object>
</span><p><a href="http://www.youtube.com/watch?v=2KggRjco6bs&fmt=18">www.youtube.com/watch?v=2KggRjco6bs</a></p></p>
<p style="clear: both">Here are some screenshots of the application in case you want to skip the video.</p>
<p style="clear: both">
<div class="ngg-galleryoverview" id="ngg-gallery-1-2628">

	<!-- Slideshow link -->
	<div class="slideshowlink">
		<a class="slideshowlink" href="http://blog.jeffdouglas.com/2010/06/06/salesforce-chatter-for-android/?show=slide">
			[Show as slideshow]		</a>
	</div>

	
	<!-- Thumbnails -->
		
	<div id="ngg-image-1" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/chatter-android-1.png" title=" " class="shutterset_set_1"  rel="lightbox[2628]">
								<img title="chatter-android-1" alt="chatter-android-1" src="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/thumbs/thumbs_chatter-android-1.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-2" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/chatter-android-2.png" title=" " class="shutterset_set_1"  rel="lightbox[2628]">
								<img title="chatter-android-2" alt="chatter-android-2" src="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/thumbs/thumbs_chatter-android-2.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-3" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/chatter-android-3.png" title=" " class="shutterset_set_1"  rel="lightbox[2628]">
								<img title="chatter-android-3" alt="chatter-android-3" src="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/thumbs/thumbs_chatter-android-3.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-4" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/chatter-android-4.png" title=" " class="shutterset_set_1"  rel="lightbox[2628]">
								<img title="chatter-android-4" alt="chatter-android-4" src="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/thumbs/thumbs_chatter-android-4.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-5" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/chatter-android-5.png" title=" " class="shutterset_set_1"  rel="lightbox[2628]">
								<img title="chatter-android-5" alt="chatter-android-5" src="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/thumbs/thumbs_chatter-android-5.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-6" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/chatter-android-6.png" title=" " class="shutterset_set_1"  rel="lightbox[2628]">
								<img title="chatter-android-6" alt="chatter-android-6" src="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/thumbs/thumbs_chatter-android-6.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-7" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/chatter-android-7.png" title=" " class="shutterset_set_1"  rel="lightbox[2628]">
								<img title="chatter-android-7" alt="chatter-android-7" src="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/thumbs/thumbs_chatter-android-7.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-8" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/chatter-android-8.png" title=" " class="shutterset_set_1"  rel="lightbox[2628]">
								<img title="chatter-android-8" alt="chatter-android-8" src="http://blog.jeffdouglas.com/wp-content/gallery/salesforce-chatter-for-android/thumbs/thumbs_chatter-android-8.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 	 	
	<!-- Pagination -->
 	<div class='ngg-clear'></div>
 	
</div>

</p>
<p style="clear: both">I use Google App Engine to tie all of this applications together and provide a coherent security model. So I wrote <a href="http://chatter-android.appspot.com">a small App Engine app</a> that uses OAuth to authorize access to Force.com and my Chatter feeds using Force.com Remote Access Application. Once authorized the Force.com Web Services Connector, running on App Engine, performs the interactions with SFDC such as submitting new status updates, fetching my feeds and displaying them as JSON objects. </p>
<p style="clear: both">App Engine recently started supporting 2-legged <a href="http://code.google.com/appengine/docs/java/oauth/overview.html" target="_blank">OAuth in combination with Google Accounts</a> so that any App Engine application can become an OAuth service provider. Since OAuth support is baked into the Android platform I tried to hook up the Android handset as an OAuth consumer but could not finish in time to submit my entry to the Developer Challenge.</p>
<p style="clear: both"><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/06/Chatter_Android4.png" class="image-link" rel="lightbox[2628]"><img class="linked-to-original" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/06/Chatter_Android4-thumb.png" height="154" align="left" width="525" style=" display: inline; float: left; margin: 0 10px 10px 0;" /></a><br style="clear: both" />Since Android doesn&#8217;t play well with SOAP-based Web Services I think this approach in combination with JSON makes an appealing option. If you have any ideas, I&#8217;d love to hear them. I expect to write some more apps for Salesforce.com as the Android platform is fairly easy to grok. If you are familiar with using Eclipse with Force.com, App Engine, GWT or Java in general it seems much faster to get an app up and running with Android than with Objective-C for the iPhone. Just my $.02.</p>
<p style="clear: both">
<p><br class="final-break" style="clear: both" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jeffdouglas.com/2010/06/06/salesforce-chatter-for-android/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>WaveMaker&#8217;s IDE for the Cloud</title>
		<link>http://blog.jeffdouglas.com/2010/06/04/wavemakers-ide-for-the-cloud/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=wavemakers-ide-for-the-cloud</link>
		<comments>http://blog.jeffdouglas.com/2010/06/04/wavemakers-ide-for-the-cloud/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 10:44:16 +0000</pubDate>
		<dc:creator>Jeff Douglas</dc:creator>
				<category><![CDATA[Amazon EC2]]></category>
		<category><![CDATA[Cloud Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[VMforce]]></category>

		<guid isPermaLink="false">http://blog.jeffdouglas.com/?p=2620</guid>
		<description><![CDATA[Yesterday at Appirio we had a private demo of the WaveMaker platform from the guys at WaveMaker. I&#8217;ll try to recap most of the things that I heard as it pertains to Salesforce.com and vmforce but for more details you&#8217;ll want to check out their website. The WaveMaker platform allows you to build applications that [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F06%2F04%2Fwavemakers-ide-for-the-cloud%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F06%2F04%2Fwavemakers-ide-for-the-cloud%2F&amp;source=jeffdonthemic&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p style="clear: both"><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/06/wavemaker-logo.png" class="image-link" rel="lightbox[2620]"><img class="linked-to-original" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/06/wavemaker-logo-thumb1.png" height="40" align="left" width="200" style=" display: inline; float: left; margin: 0 10px 10px 0;" /></a>Yesterday at <a href="http://www.appirio.com" target="_blank">Appirio</a> we had a private demo of the WaveMaker platform from the guys at WaveMaker. I&#8217;ll try to recap most of the things that I heard as it pertains to Salesforce.com and vmforce but for more details you&#8217;ll want to check out their <a href="http://www.wavemaker.com/product/" target="_blank">website</a>. </p>
<p style="clear: both">The <a href="http://www.wavemaker.com/product/" target="_blank">WaveMaker platform</a> allows you to build applications that are portable across cloud environments. WaveMaker’s rapid application development platform consists of two products:</p>
<ul style="clear: both">
<li><strong>WaveMaker Studio</strong>: a visual, drag &#038; drop development tool that runs in a browser and can be installed on a desktop or accessed via the cloud.</li>
<li><strong>WaveMaker Server</strong>: a Java framework that provides security and data management, runs in any Java server and deploys on-site or in the cloud </li>
</ul>
<p style="clear: both">The WaveMaker Studio is a pretty slick drag-n-drop interface with live previews of data for bound widgets. You can consume Web Services, database schemas and Java services to automatically generate boilerplate code for you. On the frontend it generates Dojo widgets and Spring and Hibernate components for the backend. It essentially spits out a standard Spring application that will run in any standard J2EE environment.</p>
<p style="clear: both">Development features include: </p>
<ul style="clear: both">
<li>Drag &#038; drop application assembly</li>
<li>One-click database import</li>
<li>One-click CRUD data forms</li>
<li>One-click related data forms</li>
<li>Live data preview within studio</li>
<li>Single sign-on security</li>
<li>Role-based access controls</li>
<li>Rich entry field validation</li>
<li>Built-in data grid pagination</li>
<li>Auto-complete search boxes</li>
</ul>
<p style="clear: both">So how does this related to Salesforce.com? They are working for a release in July that supports the Force.com platform and will run on VMforce. They can consume the Enterprise WSDL and generate a standard front and back end components that you can import into Eclipse and start customizing. Their goal is to treat Salesforce just like any other database. However they are trying to build in some platform logic such as governor and limits based up the running edition. These java apps can then be deployed to EC2 and VMforce.</p>
<p style="clear: both"><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/06/wavemaker-1.png" class="image-link" rel="lightbox[2620]"><img class="linked-to-original" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/06/wavemaker-1-thumb.png" height="283" align="left" width="380" style=" display: inline; float: left; margin: 0 10px 10px 0;" /></a><br style="clear: both" />If you are interested, there is a free, community edition you can <a href="http://www.wavemaker.com/product/cloud.html" target="_blank">get started with right away</a>. I&#8217;m not sure of the pricing for their enterprise or cloud editions so you&#8217;ll want to check with them if they have a seat and/or runtime license before you invest too much time.</p>
<p style="clear: both">Some other interesting points from yesterday&#8217;s meeting:</p>
<p style="clear: both">
<ul style="clear: both">
<li>Web Fast: with WaveMaker&#8217;s visual tools, any developer can start building enterprise Java applications with minimal training.</li>
<li>CIO Safe: WaveMaker creates standard Java applications, boosting developer productivity and quality without compromising flexibility.</li>
<li>Cloud Ready: WaveMaker enables one-click deployment of rich internet applications to on-site or cloud hosting.</li>
<li>Cuts Java learning curve 92%: College grads can build Java web apps in 2 months versus 2 years</li>
<li>Reduces code 98%: Migrated .NET app with 26K lines of code to WaveMaker with 335 lines.</li>
<li>Slashes maintenance 75%: Self-service for call center app eliminates 75% of maintenance costs</li>
</ul>
<p><br class="final-break" style="clear: both" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jeffdouglas.com/2010/06/04/wavemakers-ide-for-the-cloud/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java Command Line App Using the Salesforce WSC</title>
		<link>http://blog.jeffdouglas.com/2010/05/17/java-command-line-app-using-the-salesforce-wsc/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=java-command-line-app-using-the-salesforce-wsc</link>
		<comments>http://blog.jeffdouglas.com/2010/05/17/java-command-line-app-using-the-salesforce-wsc/#comments</comments>
		<pubDate>Mon, 17 May 2010 12:42:27 +0000</pubDate>
		<dc:creator>Jeff Douglas</dc:creator>
				<category><![CDATA[Code Sample]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Salesforce]]></category>

		<guid isPermaLink="false">http://blog.jeffdouglas.com/?p=2545</guid>
		<description><![CDATA[The Force.com Web Service Connector (WSC) is a high performance web services stack that is much easier to implement than the &#8220;tried and true&#8221; Force.com Web Services API. Here&#8217;s a quick command line app you can use as a starter application. This class simply creates a new Account and then queries for the 5 newest [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F05%2F17%2Fjava-command-line-app-using-the-salesforce-wsc%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F05%2F17%2Fjava-command-line-app-using-the-salesforce-wsc%2F&amp;source=jeffdonthemic&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><a href="http://code.google.com/p/sfdc-wsc/"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/05/wsc-logo.png" alt="" title="wsc-logo" width="319" height="56" class="alignleft size-full wp-image-2560" /></a>The <a href="http://code.google.com/p/sfdc-wsc/" target="_blank">Force.com Web Service Connector</a> (WSC) is a high performance web services stack that is much easier to implement than the &#8220;tried and true&#8221; <a href="http://www.salesforce.com/us/developer/docs/api/index.htm" target="_blank">Force.com Web Services API</a>. Here&#8217;s a quick command line app you can use as a starter application. This class simply creates a new Account and then queries for the 5 newest Accounts by created date.</p>
<p>To get started, download wsc-18.jar from the <a href="http://code.google.com/p/sfdc-wsc/downloads/list" target="_blank">WSC project&#8217;s download page</a> to your desktop (any location will do). Now log into your Developer org and download the Partner WSDL (Setup -> App Setup -> Develop -> API) to your desktop as &#8220;partner.wsdl&#8221;. Now we&#8217;ll need to generate the stub code from the Partner WSDL. Make sure you have Java 1.6 installed and open a command prompt. Now run wsdlc on the Partner WSDL you just downloaded (detailed instruction are <a href="http://code.google.com/p/sfdc-wsc/wiki/GettingStarted" target="_blank">here</a>):</p>
<blockquote><p>java -classpath wsc-18.jar com.sforce.ws.tools.wsdlc partner.wsdl partner.jar</p></blockquote>
<p>This will create a &#8220;partner.jar&#8221; file on your desktop. If you are using a Sandbox instead of a Developer or Production org, <a href="http://blog.jeffdouglas.com/2010/03/11/error-compiling-wsc-appengine-partner-jar-for-sandbox/" target="_blank">here are instructions</a> for running wsdlc as there are a few issues. Your console should look similar to:</p>
<p><a href="http://blog.jeffdouglas.com/2010/05/17/java-command-line-app-using-the-salesforce-wsc/wsc-console/" rel="attachment wp-att-2570"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/05/wsc-console.png" alt="" title="wsc-console" width="550" class="alignnone size-full wp-image-2570" /></a></p>
<p>Note: You can also simply download the partner-18.jar and bypass the steps above to generate the partner.jar. </p>
<p>Now create a new Java project in Eclipse, add the wsc-18.jar and partner.jar files to your build path and copy the code below. You&#8217;ll need to add your username and password/security token before you run the code. Running the code should produce output similar to:</p>
<p><a href="http://blog.jeffdouglas.com/2010/05/17/java-command-line-app-using-the-salesforce-wsc/wsc-run/" rel="attachment wp-att-2583"><img src="http://blog.jeffdouglas.com/wp-content/uploads/2010/05/wsc-run.png" alt="" title="wsc-run" width="402" height="169" class="alignnone size-full wp-image-2583" /></a></p>
<p>Here&#8217;s the starter code for the application.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">package com.jeffdouglas;
&nbsp;
import com.sforce.soap.partner.*;
import com.sforce.soap.partner.sobject.*;
import com.sforce.ws.*;
&nbsp;
public class Main {
&nbsp;
  public static void main(String[] args) {
&nbsp;
    ConnectorConfig config = new ConnectorConfig();
    config.setUsername(&quot;YOUR-USERNAME&quot;);
    config.setPassword(&quot;YOUR-PASSWORD-AND-SECURITYTOKEN&quot;);
&nbsp;
    PartnerConnection connection = null;
&nbsp;
    try {
&nbsp;
      // create a connection object with the credentials
      connection = Connector.newConnection(config);
&nbsp;
      // create a new account
      System.out.println(&quot;Creating a new Account...&quot;);
      SObject account = new SObject();
      account.setType(&quot;Account&quot;);
      account.setField(&quot;Name&quot;, &quot;ACME Account 1&quot;);
      SaveResult[] results = connection.create(new SObject[] { account });
      System.out.println(&quot;Created Account: &quot; + results[0].getId());
&nbsp;
      // query for the 5 newest accounts
      System.out.println(&quot;Querying for the 5 newest Accounts...&quot;);
      QueryResult queryResults = connection.query(&quot;SELECT Id, Name from Account &quot; +
          &quot;ORDER BY CreatedDate DESC LIMIT 5&quot;);
      if (queryResults.getSize() &gt; 0) {
        for (SObject s: queryResults.getRecords()) {
          System.out.println(&quot;Id: &quot; + s.getField(&quot;Id&quot;) + &quot; - Name: &quot;+s.getField(&quot;Name&quot;));
        }
      }
&nbsp;
    } catch (ConnectionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
&nbsp;
  }
&nbsp;
}</pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.jeffdouglas.com/2010/05/17/java-command-line-app-using-the-salesforce-wsc/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Integrate Chatter &amp; Twitter on Google App Engine using OAuth</title>
		<link>http://blog.jeffdouglas.com/2010/03/17/integrate-chatter-twitter-on-google-app-engine-using-oauth/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=integrate-chatter-twitter-on-google-app-engine-using-oauth</link>
		<comments>http://blog.jeffdouglas.com/2010/03/17/integrate-chatter-twitter-on-google-app-engine-using-oauth/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 11:37:01 +0000</pubDate>
		<dc:creator>Jeff Douglas</dc:creator>
				<category><![CDATA[Code Sample]]></category>
		<category><![CDATA[GAE/J]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Salesforce]]></category>

		<guid isPermaLink="false">http://blog.jeffdouglas.com/?p=2340</guid>
		<description><![CDATA[Cross-posted at the Appirio Tech Blog. At Appirio we&#8217;ve been excited about Salesforce Chatter for quite a while. We firmly believe that Chatter has the potential to bridge the gap between enterprise applications and the way people work. We were luckily enough to receive special prerelease access to Chatter to develop our Social PS Enterprise [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F03%2F17%2Fintegrate-chatter-twitter-on-google-app-engine-using-oauth%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.jeffdouglas.com%2F2010%2F03%2F17%2Fintegrate-chatter-twitter-on-google-app-engine-using-oauth%2F&amp;source=jeffdonthemic&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p style="clear: both">Cross-posted at the <a href="http://techblog.appirio.com/2010/03/integrate-chatter-twitter-on-google-app.html">Appirio Tech Blog</a>.</p>
<p style="clear: both">At <a href="http://www.appirio.com" target="_blank">Appirio</a> we&#8217;ve been excited about Salesforce Chatter for quite a while. We firmly believe that Chatter has the potential to bridge the gap between enterprise applications and the way people work. We were luckily enough to receive special prerelease access to Chatter to develop our Social PS Enterprise for the Dreamforce &#8217;09 Chatter Keynote and if you missed the demo at Dreamforce &#8217;09 you can <a href="http://www.youtube.com/watch?v=Xu-2ZgrmBhs&#038;feature=player_embedded#" target="_blank">find it here</a>.</p>
<p style="clear: both">Chatter is now in private beta for 100 companies and it is enabled in our production org. We&#8217;ve been using it for couple of weeks now and I find myself logging into our org more and more to check the status of other employees, projects and opportunities. As a developer I really wanted to get my hands on the code and test drive Chatter&#8217;s functionality. Luckily Quinton Wall has a great <a href="http://wiki.developerforce.com/index.php/An_Introduction_to_Salesforce_Chatter" target="_blank">Intro to Chatter</a> on developer.force.com to get me started. Sure, I could have developed an Apex and Visualforce application for Chatter but I naturally wanted to integrate Chatter with Twitter. So what I came up with is a Chatter/Twitter app running on Google App Engine using OAuth for Twitter authentication.</p>
<p><span class="youtube">
<object width="560" height="340">
<param name="movie" value="http://www.youtube.com/v/FqeGxAuFqSM?color1=d6d6d6&amp;color2=f0f0f0&amp;border=0&amp;fs=1&amp;hl=en&amp;loop=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0&amp;rel=1&amp;hd=1&#038;w=550" />
<param name="allowFullScreen" value="true" />
<embed wmode="opaque" src="http://www.youtube.com/v/FqeGxAuFqSM?color1=d6d6d6&amp;color2=f0f0f0&amp;border=0&amp;fs=1&amp;hl=en&amp;loop=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0&amp;rel=1&amp;hd=1&#038;w=550" type="application/x-shockwave-flash" allowfullscreen="true" width="560" height="340"></embed>
<param name="wmode" value="opaque" />
</object>
</span><p><a href="http://www.youtube.com/watch?v=FqeGxAuFqSM&fmt=18">www.youtube.com/watch?v=FqeGxAuFqSM</a></p></p>
<p style="clear: both"><strong>Understanding Chatter</strong></p>
<p style="clear: both">Initially I was under the assumption that Salesforce.com would release some sort of API for Chatter. However, they&#8217;ve done something even better. Instead of a new API to learn, Salesforce.com exposed Chatter as a series of sObjects allowing you to query for records using the same SOQL that you know and love and manipulate records using DML. Once you get a grip on the Chatter object model and where data lives, developing applications for Chatter is essentially the same as using the Sales or Service Could.</p>
<p style="clear: both"><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/03/600px-DataModel2.png" class="image-link" rel="lightbox"><img class="linked-to-original" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/03/600px-DataModel2-thumb.png" height="308" align="left" width="550" style=" display: inline; float: left; margin: 0 10px 10px 0;" /></a><br style="clear: both" />The Chatter model is based upon familiar social networking &#8220;Feed Posts&#8221;. These posts are made up of a series of Feed Items and Feed Types. The FeedPost stores most of the information that you are concerned about such as the body, title and any content related data. The FeedPost object also contains the information for all posts for the User object including profile statuses, news feeds and entity updates (accounts, contacts or custom objects). The Feed Types are dependent on what actions you are performing:</p>
<ul style="clear: both">
<li> UserStatus - this is the user status update (e.g., &#8220;What are you working on?&#8221;)</li>
<li> TextPost - a post you make from a record</li>
<li> LinkPost - a post that contains a URL link (when you click on the link icon)</li>
<li> ContentPost - a post that contains some type of uploaded content such as a document or graphic</li>
<li> TrackedChanges - whenever a field on a record (set up during Chatter Feed Tracking configuration) is updated</li>
</ul>
<p style="clear: both">One thing to understand from the beginning is that you do not query for Feed Posts directly. You must query via the Feed Item which contains a reference to the details of the post. So to get the last status update for the current user, you would issue the following SOQL:</p>
<p style="clear: both"  style="font-family:courier new;">SELECT Id, FeedPost.Body FROM UserFeed WHERE ParentId = :Userinfo.getUserId()<br />And Type = &#8216;UserStatus&#8217; ORDER BY CreatedDate DESC LIMIT 1</p>
<p style="clear: both">For more sample Chatter code, check out the <a href="http://wiki.developerforce.com/index.php/Chatter_Code_Recipes" target="_blank">Chatter Code Recipes</a>.</p>
<p style="clear: both"><strong>Functional Design</strong></p>
<p style="clear: both">From a high-level overview, the application is fairly simple. When it initially loads the user is prompted to log into Twitter using OAuth.</p>
<p style="clear: both"><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/03/chatter1.png" class="image-link" rel="lightbox"><img class="linked-to-original" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/03/chatter1-thumb.png" height="326" align="left" width="550" style=" display: inline; float: left; margin: 0 10px 10px 0;" /></a><br style="clear: both" />Twitter asks you to grant the App Engine application the ability to access and update your Twitter account. I&#8217;m currently working on OAuth for Salesforce.com and hope to have both sides of the application using OAuth soon. Currently my Salesforce.com sandbox credentials are hard-coded in the application.</p>
<p style="clear: both"><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/03/chatter2.png" class="image-link" rel="lightbox"><img class="linked-to-original" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/03/chatter2-thumb.png" height="325" align="left" width="547" style=" display: inline; float: left; margin: 0 10px 10px 0;" /></a><br style="clear: both" />Once you authorize access you are redirected back to the application on Google App Engine and presented the following options:</p>
<p style="clear: both">
<ul style="clear: both">
<li>Send your latest tweet to Chatter - fetches your last tweet from your timeline and sends it to Chatter as a status update.</li>
<li>Tweet your latest Chatter status update - queries for you last Chatter update and tweets it. Since Chatter is designed to be private within your org this option isn&#8217;t recommended for production and I only implemented it for academic purposes.</li>
<li>Send a status update to both Chatter and Twitter - presents you with a simple form to enter your status update. Once the form is submitted, your status is sent to both Chatter and Twitter.</li>
</ul>
<p style="clear: both"><a href="http://blog.jeffdouglas.com/wp-content/uploads/2010/03/chatter3.png" class="image-link" rel="lightbox"><img class="linked-to-original" src="http://blog.jeffdouglas.com/wp-content/uploads/2010/03/chatter3-thumb.png" height="325" align="left" width="547" style=" display: inline; float: left; margin: 0 10px 10px 0;" /></a><br style="clear: both" /><strong>Technical Design</strong></p>
<p style="clear: both">The application is developed on Google App Engine using the <a href="http://code.google.com/p/sfdc-wsc/" target="_blank">Force.com Web Service Connector (WSC)</a>, Salesfore.com Partner library, and the <a href="http://twitter4j.org/en/index.html" target="_blank">Twitter4j</a> Java library. Since we are using Google App Engine, download the wsc-gae-16_0.jar and partner-library.jar Jars from the <a href="http://code.google.com/p/sfdc-wsc/downloads/list" target="_blank">WSC project</a>. I used Chatter on one of our sandboxes so I had to do a <a href="http://blog.jeffdouglas.com/2010/03/11/error-compiling-wsc-appengine-partner-jar-for-sandbox/" target="_blank">little tweaking</a> to get the Partner jar running. Now create a new Web Application Project for App Engine and then drop your two jars and the twitter4j jar into the lib directory. You&#8217;ll also need to add them to your project&#8217;s build path in Eclipse.</p>
<p style="clear: both">Next you&#8217;ll have to <a href="http://twitter.com/oauth" target="_blank">register your app</a> with Twitter. This will give you the consumer key, consumer secret and URLs you&#8217;ll need to authenticate and make requests to Twitter. I&#8217;m storing these credentials along with the Salesforce.com sandbox credentials and user id as static variables in a simple credentials class for ease of use.</p>
<p style="clear: both">The<br />
 application is a series of JSPs and Servlets and if you&#8217;d like the code for the entire project, <a href="http://www.twitter.com/jeffdonthemic" target="_blank">send me a message</a>. The interesting parts of the application are described below and hopefully you can extrapolate the rest.</p>
<p style="clear: both"><strong>LoginServlet</strong></p>
<p style="clear: both">This is the initial request for the application. The code uses the Twitter credentials and gets the authorization URL for the app and presents it to the users in the JSP page. The user clicks this link and is taken to Twitter to authorize the application.</p>
<p style="clear: both">

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">package com.jeffdouglas;
&nbsp;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import org.apache.log4j.Logger;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.http.RequestToken;
&nbsp;
public class LoginServlet extends HttpServlet {
&nbsp;
  private static final Logger log = Logger.getLogger(LoginServlet.class);
&nbsp;
  public void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
&nbsp;
    HttpSession session = req.getSession();
    Twitter twitter = new TwitterFactory().getInstance();
    twitter.setOAuthConsumer(Credentials.TWITTER_CONSUMERKEY,Credentials.TWITTER_CONSUMERSECRET);
    RequestToken requestToken = null;
&nbsp;
    try {
      requestToken = twitter.getOAuthRequestToken();
    } catch (TwitterException e) {
      log.error(e.toString());
    }
&nbsp;
    // get the token and tokenSecret
    String token = (String)requestToken.getToken();
    String tokenSecret = (String)requestToken.getTokenSecret();
    // store the token and tokenSecret in the session
    session.setAttribute(&quot;token&quot;, token);
    session.setAttribute(&quot;tokenSecret&quot;, tokenSecret);
&nbsp;
    // get the url that the user must click to authenticate w/OAuth
    String authUrl = requestToken.getAuthorizationURL();
    req.setAttribute(&quot;authUrl&quot;, authUrl);
    RequestDispatcher rd = req.getRequestDispatcher(&quot;login.jsp&quot;);
&nbsp;
    try {
      rd.forward(req, resp);
    } catch (ServletException e) {
      log.error(e.toString());
    }
&nbsp;
  }
}</pre></td></tr></table></div>

</p>
<p style="clear: both"><strong>SendChatterServlet</strong></p>
<p style="clear: both">This Servlet runs when the user clicks the Twitter -> Chatter link. The code grabs the user&#8217;s last tweet and the uses the Partner Web Services API to submit the sObject with the new Chatter status to Salesforce.com.</p>
<p style="clear: both">

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">package com.jeffdouglas;
&nbsp;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.http.AccessToken;
&nbsp;
import com.sforce.ws.*;
import com.sforce.soap.partner.*;
import com.sforce.soap.partner.sobject.SObject;
&nbsp;
public class SendChatterServlet extends HttpServlet {
&nbsp;
  private static final Logger log = Logger.getLogger(SendTweetServlet.class);
&nbsp;
  public void doGet(HttpServletRequest req, HttpServletResponse resp)
  throws IOException {
&nbsp;
    PartnerConnection connection = null;
    // get the user's last tweet
    String tweet = getLastTweet(req,resp);
&nbsp;
    if (tweet != null) {
&nbsp;
      try {
        if (connection == null) {
          ConnectorConfig config = new ConnectorConfig();
          config.setUsername(Credentials.SFDC_USERNAME);
          config.setPassword(Credentials.SFDC_PASSWORD);
          connection = Connector.newConnection(config);
        }
&nbsp;
        // create the sobject to hold the post
        SObject post = new SObject();
        post.setType(&quot;FeedPost&quot;);
        post.setField(&quot;ParentId&quot;, Credentials.SFDC_USERID);
        post.setField(&quot;Body&quot;, tweet);
        // submit the update to Salesforce.com
        connection.create(new SObject[]{post});
&nbsp;
      } catch (ConnectionException ce) {
        log.error(ce.toString());
      }
&nbsp;
      resp.getWriter().println(&quot;Tweet sent to Chatter: &quot;+tweet);
    } else {
      resp.getWriter().println(&quot;Could not fetch the lastes update from Twitter. Nothing sent to Chatter.&quot;);
    }
&nbsp;
  }
&nbsp;
  private String getLastTweet(HttpServletRequest req, HttpServletResponse resp) {
&nbsp;
    String tweet = null;
    HttpSession session = req.getSession();
    Twitter twitter = new TwitterFactory().getInstance();
&nbsp;
    twitter.setOAuthConsumer(Credentials.TWITTER_CONSUMERKEY,
        Credentials.TWITTER_CONSUMERSECRET);
&nbsp;
    // if the access token is present in the session
    if (session.getAttribute(&quot;accessToken&quot;) == null){
        // get the request token from the session
        String token = (String) session.getAttribute(&quot;token&quot;);
        String tokenSecret = (String)session.getAttribute(&quot;tokenSecret&quot;);
&nbsp;
        // get the access token from twitter
        AccessToken accessToken = null;
        try {
          accessToken = twitter.getOAuthAccessToken(token, tokenSecret);
        } catch (TwitterException e) {
          log.error(e.toString());
        }
        twitter.setOAuthAccessToken(accessToken);
&nbsp;
        // save the access token, that are different from request token
        session.setAttribute(&quot;accessToken&quot;, accessToken.getToken());
        session.setAttribute(&quot;accessTokenSecret&quot;, accessToken.getTokenSecret());
&nbsp;
    } else {
        // use the access token from the session
        twitter.setOAuthAccessToken((String)session.getAttribute(&quot;accessToken&quot;),
            (String)session.getAttribute(&quot;accessTokenSecret&quot;));
    }
&nbsp;
    List&lt;status&gt; statuses = null;
    try {
      // get the user's timeline
      statuses = twitter.getUserTimeline();
      // set their last tweet to return
      tweet = statuses.get(0).getText();
    } catch (TwitterException e) {
      log.error(e.toString());
    }
&nbsp;
    return tweet;
&nbsp;
  }
&nbsp;
}</pre></td></tr></table></div>

</p>
<p style="clear: both"><strong>SendTweetServlet</strong></p>
<p style="clear: both">When the user clicks the Chatter -> Twitter link, this Servlet queries Salesforce.com for the user&#8217;s most recent status update, finds the status in the returned XML results and then sends the status out as a tweet.</p>
<p style="clear: both">

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">package com.jeffdouglas;
&nbsp;
import java.io.IOException;
import java.util.Iterator;
import javax.servlet.http.*;
import org.apache.log4j.Logger;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.http.AccessToken;
&nbsp;
import com.sforce.ws.*;
import com.sforce.ws.bind.XmlObject;
import com.sforce.soap.partner.*;
import com.sforce.soap.partner.sobject.SObject;
&nbsp;
public class SendTweetServlet extends HttpServlet {
&nbsp;
  private static final Logger log = Logger.getLogger(SendTweetServlet.class);
&nbsp;
  public void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
&nbsp;
    PartnerConnection connection = null;
    String feedPost = null;
&nbsp;
    try {
      if (connection == null) {
        ConnectorConfig config = new ConnectorConfig();
        config.setUsername(Credentials.SFDC_USERNAME);
        config.setPassword(Credentials.SFDC_PASSWORD);
        connection = Connector.newConnection(config);
      }
&nbsp;
      QueryResult results = connection
          .query(&quot;SELECT Id, FeedPost.Body FROM UserFeed WHERE &quot;
              + &quot;ParentId = '&quot; + Credentials.SFDC_USERID + &quot;'&quot;
              + &quot; And Type = 'UserStatus' ORDER BY CreatedDate DESC LIMIT 1&quot;);
&nbsp;
      // in this case there will only be 1 record returned, but....
      for (int i = 0; i &lt; results.getRecords().length; i++) {
        SObject feed = results.getRecords()[i];
        feedPost = getFeedBody(feed);
      }
&nbsp;
    } catch (ConnectionException ce) {
      log.error(ce.toString());
    }
&nbsp;
    if (feedPost != null) {
      sendTweet(feedPost, req, resp);
      resp.getWriter().println(&quot;Chatter message sent to Twitter: &quot; + feedPost);
    } else {
      resp.getWriter().println(&quot;Nothing sent to Twitter&quot;);
    }
&nbsp;
  }
&nbsp;
  private void sendTweet(String tweet, HttpServletRequest req, HttpServletResponse resp) {
&nbsp;
    HttpSession session = req.getSession();
    Twitter twitter = new TwitterFactory().getInstance();
&nbsp;
    twitter.setOAuthConsumer(Credentials.TWITTER_CONSUMERKEY,
        Credentials.TWITTER_CONSUMERSECRET);
&nbsp;
    // if the access token is present in the session
    if (session.getAttribute(&quot;accessToken&quot;) == null){
        // get the request token from the session
        String token = (String) session.getAttribute(&quot;token&quot;);
        String tokenSecret = (String)session.getAttribute(&quot;tokenSecret&quot;);
&nbsp;
        // get the access token from twitter
        AccessToken accessToken = null;
        try {
          accessToken = twitter.getOAuthAccessToken(token, tokenSecret);
        } catch (TwitterException e) {
          log.error(e.toString());
        }
        twitter.setOAuthAccessToken(accessToken);
&nbsp;
        // save the access token, that are different from request token
        session.setAttribute(&quot;accessToken&quot;, accessToken.getToken());
        session.setAttribute(&quot;accessTokenSecret&quot;, accessToken.getTokenSecret());
&nbsp;
    } else {
        // use the access token from the session
        twitter.setOAuthAccessToken((String)session.getAttribute(&quot;accessToken&quot;),
            (String)session.getAttribute(&quot;accessTokenSecret&quot;));
    }
&nbsp;
    try {
      // update the user's twitter status
      twitter.updateStatus(tweet);
    } catch (TwitterException e) {
      log.error(e.toString());
    }
&nbsp;
  }
&nbsp;
  private String getFeedBody(SObject feed) {
    String feedBody = &quot;&quot;;
    Iterator&lt;xmlObject&gt; feedPost = feed.getChildren();
    while (feedPost.hasNext()) {
      XmlObject post = feedPost.next();
      if (post.getValue() == null) {
        Iterator&lt;xmlObject&gt; body = post.getChildren();
        while (body.hasNext()) {
          XmlObject child = body.next();
          if (child.getName().toString().equals(
              &quot;{urn:sobject.partner.soap.sforce.com}Body&quot;)) {
            feedBody = child.getValue().toString();
            break;
          }
        }
      }
    }
    return feedBody;
  }
}</pre></td></tr></table></div>

</p>
<p style="clear: both"><strong>SendBothServlet</strong></p>
<p style="clear: both">This Servlet loads the HTML form presenting the user with a textbox to enter their new status. When the form is posted, the status is sent out to both Chatter and Twitter.</p>
<p style="clear: both">

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">package com.jeffdouglas;
&nbsp;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.http.AccessToken;
&nbsp;
import com.sforce.soap.partner.Connector;
import com.sforce.soap.partner.PartnerConnection;
import com.sforce.soap.partner.sobject.SObject;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;
&nbsp;
public class SendBothServlet extends HttpServlet {
&nbsp;
  private static final Logger log = Logger.getLogger(SendTweetServlet.class);
&nbsp;
  private void sendToChatter(String status) {
&nbsp;
    PartnerConnection connection = null;
&nbsp;
      try {
        if (connection == null) {
          ConnectorConfig config = new ConnectorConfig();
          config.setUsername(Credentials.SFDC_USERNAME);
          config.setPassword(Credentials.SFDC_PASSWORD);
          connection = Connector.newConnection(config);
        }
&nbsp;
        // create the sobject to hold the post
        SObject post = new SObject();
        post.setType(&quot;FeedPost&quot;);
        post.setField(&quot;ParentId&quot;, Credentials.SFDC_USERID);
        post.setField(&quot;Body&quot;, status);
        // submit the update to Salesforce.com
        connection.create(new SObject[]{post});
&nbsp;
      } catch (ConnectionException ce) {
        log.error(ce.toString());
      }
&nbsp;
  }
&nbsp;
  private void sendToTwitter(String status, HttpServletRequest req) {
&nbsp;
    HttpSession session = req.getSession();
    Twitter twitter = new TwitterFactory().getInstance();
&nbsp;
    twitter.setOAuthConsumer(Credentials.TWITTER_CONSUMERKEY,
        Credentials.TWITTER_CONSUMERSECRET);
&nbsp;
    // if the access token is present in the session
    if (session.getAttribute(&quot;accessToken&quot;) == null){
        // get the request token from the session
        String token = (String) session.getAttribute(&quot;token&quot;);
        String tokenSecret = (String)session.getAttribute(&quot;tokenSecret&quot;);
&nbsp;
        // get the access token from twitter
        AccessToken accessToken = null;
        try {
          accessToken = twitter.getOAuthAccessToken(token, tokenSecret);
        } catch (TwitterException e) {
          log.error(e.toString());
        }
        twitter.setOAuthAccessToken(accessToken);
&nbsp;
        // save the access token, that are different from request token
        session.setAttribute(&quot;accessToken&quot;, accessToken.getToken());
        session.setAttribute(&quot;accessTokenSecret&quot;, accessToken.getTokenSecret());
&nbsp;
    } else {
        // use the access token from the session
        twitter.setOAuthAccessToken((String)session.getAttribute(&quot;accessToken&quot;),
            (String)session.getAttribute(&quot;accessTokenSecret&quot;));
    }
&nbsp;
    try {
      // update the user's twitter status
      twitter.updateStatus(status);
    } catch (TwitterException e) {
      log.error(e.toString());
    }
&nbsp;
  }
&nbsp;
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
  throws IOException {
&nbsp;
    sendToChatter(req.getParameter(&quot;status&quot;));
    sendToTwitter(req.getParameter(&quot;status&quot;),req);
&nbsp;
    resp.getWriter().println(&quot;Sent the following to both Chatter and Twitter: &quot;+req.getParameter(&quot;status&quot;));
&nbsp;
  }
&nbsp;
  public void doGet(HttpServletRequest req, HttpServletResponse resp)
  throws IOException {
&nbsp;
    try {
      RequestDispatcher rd = req.getRequestDispatcher(&quot;post.jsp&quot;);
      rd.forward(req, resp);
    } catch (ServletException e) {
      log.error(e.toString());
    }
&nbsp;
  }
&nbsp;
}</pre></td></tr></table></div>

</p>
<p><br class="final-break" style="clear: both" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jeffdouglas.com/2010/03/17/integrate-chatter-twitter-on-google-app-engine-using-oauth/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

