1

I am trying to replicate the Google App Engine Servlets module here using Retrofit instead of AsyncTask.

I find it odd, but apparently Retrofit 2.0 does not support connections to Google App Engine, as stated here in the issues of the GitHub repository.

As a result, I am using Retrofit 1.9 and OkHttp 2.3 dependencies.

I have created a project called "Retrofit Test" in the Google Developer Console, and Google has supplied me with a URL for the project: "http://retrofit-test-1203.appspot.com" with the subdomain as "http://retrofit-test-1203.appspot.com/hello. These will be my respective URL's for Retrofit. Below is my code:

Gradle:

apply plugin: 'com.android.application'

android {
compileSdkVersion 23
buildToolsVersion "23.0.1"

defaultConfig {
    applicationId "com.troychuinard.retrofittest"
    minSdkVersion 16
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
 } 
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.3.0'


}

MainActivity:

public class MainActivity extends AppCompatActivity {

//set the URL of the server, as defined in the Google Servlets Module Documentation
private static String PROJECT_URL = "http://retrofit-test-1203.appspot.com";
private Button mTestButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    mTestButton = (Button) findViewById(R.id.test_button);



    //Instantiate a new UserService object, and call the "testRequst" method, created in the interface
    //to interact with the server
    mTestButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Instantiate a new RestAdapter Object, setting the endpoint as the URL of the server
            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setEndpoint(PROJECT_URL)
                    .setClient(new OkClient(new OkHttpClient()))
                    .build();

            UserService userService = restAdapter.create(UserService.class);
            userService.testRequest("Test_Name", new Callback<String>() {
                @Override
                public void success(String s, Response response) {
                    Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();

                }

                @Override
                public void failure(RetrofitError error) {
                    Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
                }
            });
        }
    });


   }
}

UserService (Retrofit)

public interface UserService {

@POST("/hello")
void testRequest(@Query("name") String name, Callback<String> cb);

}

My Servlet:

public class MyServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
    resp.setContentType("text/plain");
    resp.getWriter().println("Please use the form to POST to this url");
}

@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
    String name = req.getParameter("name");
    resp.setContentType("text/plain");
    if(name == null) {
        resp.getWriter().println("Please enter a name");
    }
    resp.getWriter().println("Hello " + name);
  }
}

As you can see, I have set the project up so that I make a server request on a button click. Similar to the Google App Engine Servlets module, I am expecting to receive a response from the Server, which I then display as a Toast that says "Hello + (whatever parameter entered into the .testRequest() method, which is "Test_Name" in this case. I am receiving the error below, any help/advice on my methodology is appreciated:

enter image description here

tccpg288
  • 3,242
  • 5
  • 35
  • 80

2 Answers2

0

The problem here is that you are trying to send a POST with the "name" parameter as a @Query, when you should be sending as a @Field.

try the method like this:

@FormUrlEncoded
@POST("/hello") 
void testRequest(@Field("name") String name, Callback<String> cb);
Mateus Brandao
  • 900
  • 5
  • 9
0

You're returning a plain text response, and from the error message I assume Retrofit expects a JSON formatted response. Either:

  • try changing resp.setContentType("text/plain"); to resp.setContentType("application/json"); and change the content to JSON format

  • or check this question to read the string from the response: Retrofit callback get response body

Community
  • 1
  • 1
András Kerekes
  • 1,001
  • 7
  • 13
  • When you say change the content to JSON format, what are you referring to (in addition to that code snippet you provided)? – tccpg288 Jan 28 '16 at 18:34
  • The servlet returns a plain string like `"Hello " + name`. This is not in JSON format. I'm not sure what would be the expected format, but an example JSON would look like `"{ \"response\": \"Hello" + name + "\"}"` which would be rendered as `{ "response": "Hello World" }` – András Kerekes Jan 28 '16 at 18:45
  • Thanks! I will have to play around with it. My ultimate goal was to replace the AsyncTask with Retrofit, as AsyncTask seems outdated. Google App Engine has limited documentation, and I thought Retrofit would be easier but that appears not to be the case. – tccpg288 Jan 28 '16 at 18:48
  • To be honest this seems to have to do more like with which client library/framework you use (AsyncTask vs Retrofit) than App Engine, which in this case behaves as a Java servlet container, and any general documentation/tutorial on how to implement Java Servlets is helpful. – András Kerekes Jan 28 '16 at 18:53
  • Can you point me in the right direction of some relevant documentation? – tccpg288 Jan 28 '16 at 19:09
  • E.g.: http://www.tutorialspoint.com/servlets/ or http://docs.oracle.com/javaee/6/tutorial/doc/bnafd.html – András Kerekes Jan 28 '16 at 19:13
  • Thanks, I guess another issue I have to check is whether or not I am actually making a call to the server. – tccpg288 Jan 28 '16 at 20:07