function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
vjoshivjoshi 

REST API Sample Application

Hi,

 

I am trying to learn REST API through the sample application given on Force.com website. I have all the code integrated to NetBeans and I am able to put it to Tomcat server. Now, when I run the application through the browser, I get the link that says "click here to get data through REST/oauth" and then I get the salesforce login page too. But, when I type in the username and password, I get  "error 310; too many redirects" and when I reload the page, I get error in doget method that says "addparameter arguments cannot be null.

 

Please help!

cloudcodercloudcoder

which sample app are you refering to?

eustachieustachi

From the description I'm pretty sure it's this one: http://wiki.developerforce.com/index.php/Getting_Started_with_the_Force.com_REST_API

 

 

vjoshivjoshi

Yes, it is the same application.

vjoshivjoshi

I had to change the code a little bit too. For example, I initialized all the parameters in OAuthServlet.java file into web.xml and removed the javax.servlet.annotation import as my netbeans said it does not exist. So, I removed the @WebInitParam initializers instead putting them in web.xml file. Also, I could not figure out where to put the init parameters for DemoREST.java file because I see a "url pattern" defined in the starting of that file. Also, what should be the servlet name for this file and should I put parameters for this file also in web.xml?

 

 

cloudcodercloudcoder

It sounds like you are using a servlet container that doesn't support the latest spec. The @WebInitParams only came in pretty recently.

vjoshivjoshi

I have changed it to work with web.xml. Is there a way I can use it with my current servlet container. I have tomcat 6.0.32 server with servlet 2.5. The @WebInitParams comes with servlet 3.0 I guess. And I am using Netbeans 6.9.1 version of IDE. 

cloudcodercloudcoder

The REST API is not dependent on a particular version of the servlet API, but as you noticed, you will have to modify your web app config to make it work with init params etc.

vjoshivjoshi

I am trying to debug the code. I tried to print the value of tokenUrl in the browser from OAuthServlet.java file and I am getting this after putting in my username and password in the salesforce authentication page:

 

</OAuth>

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<OAuth>
<error>unsupported_grant_type</error>
<error_description>grant type not supported</error_description>
What could be the issue?
I am also attaching the code.
/**
 *
 * @author Varun
 */

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.ServletException;
//import javax.servlet.annotation.WebInitParam;
//import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;

import java.io.PrintWriter;

/**
 * Servlet parameters
 
@WebServlet(name = "oauth", urlPatterns = { "/oauth/*", "/oauth" }, initParams = {
		// clientId is 'Consumer Key' in the Remote Access UI
		@WebInitParam(name = "clientId", value = "3MVG9y6x0357HlefZvgrKO4VdcJZ7qy3A_f5Mbm8hyCOdPXgHxfpIZEpPKDwLlpQVgGHISdF6LVfPJWXRL9WB"),
		// clientSecret is 'Consumer Secret' in the Remote Access UI
		@WebInitParam(name = "clientSecret", value = "6722642051751912408"),
		// This must be identical to 'Callback URL' in the Remote Access UI
		@WebInitParam(name = "redirectUri", value = "https://128.230.184.201:8448/RestTest/oauth/_callback"),
		@WebInitParam(name = "environment", value = "https://login.salesforce.com") })
*/

public class OAuthServlet extends HttpServlet
{
    private static final long serialVersionUID = 1L;
    private static final String ACCESS_TOKEN = "ACCESS_TOKEN";
    private static final String INSTANCE_URL = "INSTANCE_URL";
    private String clientId = null;
    private String clientSecret = null;
    private String redirectUri = null;
    private String environment = null;
    private String authUrl = null;
    private String tokenUrl = null;

    @Override
    public void init() throws ServletException
    {
        clientId = this.getInitParameter("clientId");
        clientSecret = this.getInitParameter("clientSecret");
	redirectUri = this.getInitParameter("redirectUri");
	environment = this.getInitParameter("environment");

	try 
        {
            authUrl = environment
            + "/services/oauth2/authorize?response_type=code&client_id="
            + clientId + "&redirect_uri="
            + URLEncoder.encode(redirectUri, "UTF-8");
	}
        catch (UnsupportedEncodingException e)
        {
            throw new ServletException(e);
	}
	
        tokenUrl = environment + "/services/oauth2/token";
    }

    @Override
    public void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException 
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<a href="+tokenUrl+">Click here</a>");
	String accessToken = (String) request.getSession().getAttribute(ACCESS_TOKEN);
        
        if (accessToken == null)
        {
            String instanceUrl = null;
            if (request.getRequestURI().endsWith("oauth"))
            {
                out.println("<html><head><title>in if</title></head><body>inside if</body></html>");
                //out.println("<a href="+authUrl+">Click here to go back to input page</a>");
                // we need to send the user to authorize
                response.sendRedirect(authUrl);
                return;
            }
            else
            {
                System.out.println("Auth successful - got callback");
                String code = request.getParameter("code");
                HttpClient httpclient = new HttpClient();
                out.println("<html><head><title>in else</title></head><body>inside else</body></html>");
                PostMethod post = new PostMethod(tokenUrl);
		post.addParameter("code", code);
		post.addParameter("grant_type", "authorization_code");
		post.addParameter("client_id", clientId);
		post.addParameter("client_secret", clientSecret);
		post.addParameter("redirect_uri", redirectUri);
		try
                {
                    httpclient.executeMethod(post);
                    try
                    {
                        JSONObject authResponse = new JSONObject(
                                new JSONTokener(new InputStreamReader(post.getResponseBodyAsStream())));
			System.out.println("Auth response: "+ authResponse.toString(2));
                        accessToken = authResponse.getString("access_token");
			instanceUrl = authResponse.getString("instance_url");
                        System.out.println("Got access token: " + accessToken);
                    }
                    catch (JSONException e)
                    {
			throw new ServletException(e);
                    }
		} 
                finally
                {
                    post.releaseConnection();
		}
            }

	// Set a session attribute so that other servlets can get the access
	// token
	request.getSession().setAttribute(ACCESS_TOKEN, accessToken);

	// We also get the instance URL from the OAuth response, so set it
	// in the session too
	request.getSession().setAttribute(INSTANCE_URL, instanceUrl);
      }
    //response.sendRedirect(request.getContextPath() + "/DemoREST");
    }
}

 I have commented out the redirect to /DemoREST in the last line to debug and am printing something on the browser to know whast loop the application enters.

ChellappaChellappa

Hi vjoshi,

There is some modification which you need to do in your code.

 

Please find below my code.It is almost the same but it worked for me.

I am still having one problem. For Contact, i am not getting the columns whichi want. All i am getting is Id and Name of the record.

 

package myeclipse;

import java.io.IOException;
import java.io.InputStreamReader;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

public class ContactServlet extends HttpServlet {
	
	  private static final long serialVersionUID = 1L;
	    private static final String ACCESS_TOKEN = "ACCESS_TOKEN";
	    private static final String INSTANCE_URL = "INSTANCE_URL";
	    private String clientId = null;
	    private String clientSecret = null;
	    private String redirectUri = null;
	    private String environment = null;
	    private String authUrl = null;
	    private String tokenUrl = null;
		@Override
	    public void init() throws ServletException
	    {
	        clientId = this.getInitParameter("clientId");
	        clientSecret = this.getInitParameter("clientSecret");
	        redirectUri = this.getInitParameter("redirectUri");
	        environment = this.getInitParameter("environment");
	
		try 
	        {
	            authUrl = environment
	            + "/services/oauth2/authorize?response_type=code&client_id="
	            + clientId + "&redirect_uri="
	            + redirectUri;//URLEncoder.encode(redirectUri, "UTF-8");
		}
	        catch (Exception e)
	        {
	            throw new ServletException(e);
		}
		
	        tokenUrl = environment + "/services/oauth2/token";
	    }

	 public void doGet(HttpServletRequest request, HttpServletResponse response)
	    throws IOException, ServletException
	    {
		 
	        String accessToken = (String) request.getSession().getAttribute(ACCESS_TOKEN);
	        String instance_url = (String) request.getSession().getAttribute(INSTANCE_URL);
		 
		    
		    HttpClient httpclient = new HttpClient();
		    PostMethod post = new PostMethod(tokenUrl);
		    post.addParameter("grant_type", "password");
		    post.addParameter("username","******");//substitute with ur own data
		    post.addParameter("password","******");//substitute with ur own data
		    post.addParameter("client_id", clientId);
		    post.addParameter("client_secret", clientSecret);
		    post.addParameter("redirect_uri", redirectUri);
		    httpclient.executeMethod(post);

		    try
            {
                httpclient.executeMethod(post);
                try
                {
                    JSONObject authResponse = new JSONObject(
                            new JSONTokener(new InputStreamReader(post.getResponseBodyAsStream())));
                    accessToken = authResponse.getString("access_token");
                    instance_url = authResponse.getString("instance_url");
                }
                catch (JSONException e)
                {
                	throw new ServletException(e);
                }
                HttpServletResponse httpResponse = (HttpServletResponse)response;
                Cookie session = new Cookie(ACCESS_TOKEN, accessToken);
                session.setMaxAge(-1); //cookie not persistent, destroyed on browser exit
                httpResponse.addCookie(session);
                String url = "https://na10.salesforce.com/services/data/v20.0/sobjects/Contact";
                GetMethod gm = new GetMethod(url);
                gm.setRequestHeader("Authorization", "OAuth "+accessToken);
                NameValuePair[] params = new NameValuePair[1];
                params[0] = new NameValuePair("q","SELECT NAME, Email FROM Contact LIMIT 10");
                gm.setQueryString(params);
                httpclient.executeMethod(gm);
                String responseBody = gm.getResponseBodyAsString();
                System.out.println("Line no 133 "+responseBody);
                //exception handling removed for brevity
                JSONObject json = new JSONObject(responseBody);
                JSONArray results = json.getJSONArray("recentItems");
                for(int i = 0; i < results.length(); i++)
                	response.getWriter().write(results.getJSONObject(i).getString("Name")+ "\n");
            } catch(JSONException jsone)
            {
            	System.out.println("JSON Exception "+jsone);
            }
            finally
            {
                post.releaseConnection();
            }
          
	    }

}

 

 

ChellappaChellappa

In my last post ,i mentioned that i was not able to retrieve all the fields for the query.

I had to change the url variable.

String url = "https://na10.salesforce.com/services/data/v20.0/query";

 

Regards,

Chellappa

vjoshivjoshi

Hi,

 

Thanks for the reply. 

 

One question. Are you not using the DemoREST.java file now? I mean there is no redirect to that file so I guess there is no need?

 

 

vjoshivjoshi



Also,  I am unable to get the access_token and so I am getting this error when I run my application:

 

Oauhservlet.java JSONObject["access_token"] not found in doGet method.

 

cloudcodercloudcoder

I'm getting some of the other folks on the Evangelist team to run through the article and sample app to make sure everything works correctly etc. Stay tuned.

vjoshivjoshi

I was able to work the code and get some data (names) using the change suggested by Chellappa. This meant that I am not using the DemoREST.java file at all now. I have to do everything in OAuthServlet.java becauseit gives me "too many redirects" elsewise. 

 

Also, after running the application a few times, I am now getting a blank page with no records after authentication step. After opening up the catalina.out log I found out that there was an error retrieving "recent items" from the JSON. It could not find it. I did not make any changes to the code so it was working before with the same name.