So I want to add a dialog message to my app. There already an option for other types of error's. I just want to add an error for when there's no mobile data and WiFi. It's an older app, so it's taking me a bit more to understand, but here's what I got.
So here is the status code for the errors. Not sure if the codes are random or not (I didn't make this project)
public class StatusCodeUtil {
public static final int AWS_GATEWAY_ERROR = 1;
public static final int URL_INVALID = 2;
public static final int INTERNAL_SERVER_ERROR = 14;
public static final int ENDPOINT_INFO_STORAGE_INCOMPLETE = 7;
public static final int NO_PERMISSION_GET_DEVICE_ID = 8;
public static final int INVALID_API_FUNCTION = 18;
public static final int INVALID_HTTP_STATUS_CODE = -1;
public static final int NO_NETWORK_ERROR = 3; <- This is the status code I want to work
}
Here is the Callback for the errors
public abstract class ApiCallBack<T> implements Callback<ApiResponse<T>> {
private ParabitSDKBeaconApplication application;
public ApiCallBack(ParabitSDKBeaconApplication application) {
this.application = application;
}
#Override
public void onResponse(Call<ApiResponse<T>> call, Response<ApiResponse<T>> response) {
Long roundTripTime = getRoundTripTime(response);
if (response.isSuccessful()) {
ApiResponse<T> responseBody = response.body();
onApiResponse(responseBody.getMessage(), response.code(), responseBody.getData());
} else {
/**
* error level 1 (HTTP client or gateway error)
* */
String errorBodyJson = getErrorBodyStr(response);
// can not user ApiResponse<T> to catch the json here
// will lead to exception: java.lang.AssertionError: illegal type variable reference
// no good way to solve this (Gson's problem)
ApiErrorResponse errorBody = GsonUtil.jsonStrToObject(errorBodyJson,
new TypeToken<ApiErrorResponse>(){});
if (errorBody.getMessage().equalsIgnoreCase("forbidden")) { // x-api-key invalid
if (getLogControlManager().isLog()) {
Log.e(PARABIT_SDK_LOG, "AWS Gateway Error: " + errorBody.getMessage());
}
onError(new ApiErrorCodeInfo(AWS_GATEWAY_ERROR, response.code(),
errorBody.getMessage()));
} else if (errorBody.getMessage().equalsIgnoreCase(
"missing authentication token")) {
if (getLogControlManager().isLog()) {
Log.e(PARABIT_SDK_LOG, "AWS Gateway Error: " + errorBody.getMessage());
}
onError(new ApiErrorCodeInfo(INVALID_API_FUNCTION, response.code(),
errorBody.getMessage()));
} else {
if (getLogControlManager().isLog()) {
Log.e(PARABIT_SDK_LOG, "Other Error Response: " + errorBody.getMessage());
}
// should never happen for now
onError(new ApiErrorCodeInfo(INTERNAL_SERVER_ERROR, response.code(),
errorBody.getMessage()));
}
}
}
#Override
public void onFailure(Call<ApiResponse<T>> call, Throwable t) {
/**
* error level 1 (HTTP client or gateway error)
* */
if (t instanceof UnknownHostException) { // host of end point is unknown
if (getLogControlManager().isLog()) {
Log.e(PARABIT_SDK_LOG, "onFailure: " + "UnknownHostException");
}
onError(new ApiErrorCodeInfo(URL_INVALID, t.getLocalizedMessage()));
} else {
if (getLogControlManager().isLog()) {
Log.e(PARABIT_SDK_LOG, "onFailure: " + t.getLocalizedMessage());
}
onError(new ApiErrorCodeInfo(INTERNAL_SERVER_ERROR,
t.getLocalizedMessage()));
}
}
public static<T> String getErrorBodyStr(Response<ApiResponse<T>> response) {
if (response.errorBody() == null) {
return "";
}
String errorBodyStr = "";
try {
errorBodyStr = response.errorBody().string();
} catch (IOException e) {
e.printStackTrace();
}
return errorBodyStr;
}
protected Long getRoundTripTime(Response response) {
Long roundTripTime = response.raw().sentRequestAtMillis()
- response.raw().receivedResponseAtMillis();
return roundTripTime;
}
// public abstract void onSuccess(String successMsg, List<T> data);
public abstract void onApiResponse(String ApiMsg, int httpStatusCode, List<T> data);
public abstract void onError(ApiErrorCodeInfo apiErrorCodeInfo);
protected LogControlManager getLogControlManager() {
return SdkApplicationInstance.getSdkLogControlManager(application);
}
}
The code in the Activity that controls which error is shown
loginViewModel.loginStatusInfo.observe(this, loginStatusInfo -> {
if (loginStatusInfo.getStatus() == API_SUCCESS_STATUS){
hideLoadingDialog();
startHomeActivity();
}else if (loginStatusInfo.getStatus() == INTERNAL_SERVER_ERROR) {
hideLoadingDialog();
loginErrorDialog(getString(R.string.fail_to_login_server_error));
}else if(loginStatusInfo.getStatus() == NO_NETWORK_ERROR){<- I added this else if
hideLoadingDialog();
loginErrorDialog(getString(R.string.network_require_msg));
}
else {
hideLoadingDialog();
loginErrorDialog(loginStatusInfo.getMessage());
}
});
Any help will be appreciated, Thank you.
So I actually called ConectivityManager on the loginViewModel.loginStatusInfo method and it worked.
loginViewModel.loginStatusInfo.observe(this, loginStatusInfo -> {
if (loginStatusInfo.getStatus() == API_SUCCESS_STATUS){
hideLoadingDialog();
startHomeActivity();
}else if (loginStatusInfo.getStatus() == INTERNAL_SERVER_ERROR) {
hideLoadingDialog();
loginErrorDialog(getString(R.string.fail_to_login_server_error));
}else if(ConnectivityManager.TYPE_MOBILE == 0){
hideLoadingDialog();
networkErrorDialog(getString(R.string.network_require_msg));
}
else {
hideLoadingDialog();
loginErrorDialog(loginStatusInfo.getMessage());
}
});
Related
I know this is a common question, but I did all of them, still no resolved. In my MainActivity, I had a call from an ServerService.java, like this:
String randomNumber = serverService.contactServer();
In the ServerService.java, the contactServer() will call the method which contains the .enqueue:
public String contactServer() {
return requestServerService();
}
And the requestServerService() contains the code:
public String requestServerService() {
Call<RequestAttributes> call = new RetrofitConfig().getServiceRequester().requestRandomNumber();
call.enqueue(new Callback<RequestAttributes>() {
#Override
public void onResponse(Call<RequestAttributes> call, Response<RequestAttributes> response) {
if (!response.isSuccessful()) {
Log.i("Err", "Err: " + response.code());
} else {
RequestAttributes requestAttributes = response.body();
returnedValue = requestAttributes.getRandomNumber();
Log.d("jsonAnswer", "O numero aleatorio é: " + returnedValue);
}
}
#Override
public void onFailure(Call<RequestAttributes> call, Throwable t) {
Log.e("Fail", "Failed: " + t.getMessage());
}
}); return returnedValue;
The error is the returnedValue returns null. I tried debbuging, but even it doesn't reach onReponse. I know the problem must be because .enqueue is asynchronous, but how can I resolve this problem and return the request to the mainActivity?
The config of Retrofit:
public RetrofitConfig() {
this.retrofit = new Retrofit.Builder()
.baseUrl("localhost:3000/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public ServiceRequester getServiceRequester() {
return this.retrofit.create(ServiceRequester.class);
}
The POJO:
public class RequestAttributes {
#SerializedName("randomNumber")
private String randomNumber;
public String getRandomNumber() {
return randomNumber;
}
public void setRandomNumber(String randomNumber) {
this.randomNumber = randomNumber;
}
#Override
public String toString() {
return "RequestAttributes{" +
", randomNumber='" + randomNumber + '\'' +
'}';
}
}
And the request:
#GET("api/requestRandomNumber")
Call<RequestAttributes> requestRandomNumber();
The JSON answer if I request via browser:
{"randomNumber":"u845gq"}
You can pass callbacks from your MainActivity to contactServer() method
serverService.contactServer(new Callback<RequestAttributes>() {
#Override
public void onResponse(Call<RequestAttributes> call, Response<RequestAttributes> response) {
if (!response.isSuccessful()) {
Log.i("Err", "Err: " + response.code());
} else {
RequestAttributes requestAttributes = response.body();
String returnedValue = requestAttributes.getRandomNumber();
// Do what you want here with returnedValue. You are in the activity thread(MainThread or UIThread) for example someTextView.setText(returnedValue);
Log.d("jsonAnswer", "O numero aleatorio é: " + returnedValue);
}
}
#Override
public void onFailure(Call<RequestAttributes> call, Throwable t) {
Log.e("Fail", "Failed: " + t.getMessage());
}
});
Then make it void method, pass the callback to requestServerService() method
public void contactServer(Callback<RequestAttributes> callback) {
requestServerService(callback);
}
Then implement requestServerService() method like this:
public void requestServerService(Callback<RequestAttributes> callback) {
Call<RequestAttributes> call = new RetrofitConfig().getServiceRequester().requestRandomNumber();
call.enqueue(callback);
}
I have a function searchForTrips() which sends an API request and fetch some response in following way.
private void searchForTrips(){
int departurePortId = PORT_ID_LIST.get(departurePort);
int returnPortId = PORT_ID_LIST.get(returnPort);
int pax= Integer.parseInt(noOfPassengers);
String departureDatePARSED = DEPARTURE_DATE_VALUES.get(departureDate);
String returnDatePARSED = RETURN_DATE_VALUES.get(departureDate);
Call<TripSearchResponse> call = apiService.searchAvailableTrips(TripType,departurePortId,returnPortId,departureDatePARSED,returnDatePARSED,pax);
call.enqueue(new Callback<TripSearchResponse>() {
#Override
public void onResponse(Call<TripSearchResponse> call, Response<TripSearchResponse> response) {
int statusCode = response.code();
switch(statusCode){
case 200:
default:
Snackbar.make(findViewById(android.R.id.content),"Error loading data. Network Error.", Snackbar.LENGTH_LONG).show();
break;
}
}
#Override
public void onFailure(Call<TripSearchResponse> call, Throwable t) {
Log.i(TAG, t.getMessage());
Snackbar.make(findViewById(android.R.id.content),"Error loading data. Network Error.", Snackbar.LENGTH_LONG).show();
}
});
}
The purpose is to make this callback function reusable so I can call it from several activities and get requested data as I need. What is the best way to implement this?
try this way, its dynamic way and easy to use:
Create Retforit Interface:
public interface ApiEndpointInterface {
#Headers("Content-Type: application/json")
#POST(Constants.SERVICE_SEARCH_TRIP)
Call<JsonObject> searchForTrip(#Body TripRequest objTripRequest);
}
Create Retrofit Class:
public class AppEndPoint {
private static Retrofit objRetrofit;
public static ApiEndpointInterface getClient() {
if (objRetrofit == null){
objRetrofit = new Retrofit.Builder()
.baseUrl(Constants.SERVER_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return objRetrofit.create(ApiEndpointInterface.class);
}
}
Create this helper Classes/Interfaces to hold web service callback:
public enum ResponseState {
SUCCESS,
FAILURE,
NO_CONNECTION
}
public enum RequestType {
SEARCH_FOR_TRIP // add name for each web service
}
public class Response {
public ResponseState state;
public boolean hasError;
public RequestType requestType;
public JsonObject result;
}
public interface RestRequestInterface {
void Response(Response response);
Context getContext();
}
public class ResponseHolder { used to hold the Json response could be changed as your response
#SerializedName("is_successful")
#Expose
private boolean isSuccessful;
#SerializedName("error_message")
#Expose
private String errorMessage;
public boolean isSuccessful() {
return isSuccessful;
}
public void setSuccessful(boolean successful) {
isSuccessful = successful;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
public class AppClient {
private static ApiEndpointInterface objApiEndpointInterface;
private static Response objResponse;
private static Call<JsonObject> objCall;
// implement new method like below for each new web service
public static void searchForTrip(TripRequest objTripRequest, RestRequestInterface objRestRequestInterface) {
objResponse = new Response();
objResponse.state = ResponseState.FAILURE;
objResponse.hasError = true;
objResponse.requestType = RequestType.SEARCH_FOR_TRIP; // set type of the service from helper interface
objApiEndpointInterface = AppEndPoint.getClient();
objCall = objApiEndpointInterface.searchForTrip(objTripRequest);
handleCallBack(objRestRequestInterface);
}
private static void handleCallBack(final RestRequestInterface objRestRequestInterface) {
objCall.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, retrofit2.Response<JsonObject> response) {
try {
ResponseHolder objResponseHolder = new Gson().fromJson(response.body(), ResponseHolder.class);
if (objResponseHolder.isSuccessful()) {
objResponse.state = ResponseState.SUCCESS;
objResponse.hasError = false;
objResponse.result = response.body();
} else {
objResponse.errorMessage = objResponseHolder.getErrorMessage();
}
objRestRequestInterface.Response(objResponse);
} catch (Exception objException) {
objResponse.errorMessage = objRestRequestInterface.getContext().getString(R.string.server_error);
objRestRequestInterface.Response(objResponse);
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable objThrowable) {
String errorMessage = "";
if (objThrowable instanceof IOException) {
errorMessage = objRestRequestInterface.getContext().getString(R.string.no_connection_error);
} else {
errorMessage = objRestRequestInterface.getContext().getString(R.string.server_error);
}
objResponse.errorMessage = errorMessage;
objRestRequestInterface.Response(objResponse);
}
});
}
}
then go to your activity of fragment and make the call like this:
public class MainActivity extends AppCompatActivity implements RestRequestInterface {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initialize ids
// prepare to call web service
// 1.Initialize your object to be sent over web service
TripRequest objTripRequest = new TripRequest();
objTripRequest.id = 1;
// 2.Show loader
// 3.Make the call
AppClient.searchForTrip(objTripRequest, this);
}
#Override
public void Response(Response response) {
// hide loader
try {
if (response.state == ResponseState.SUCCESS && !response.hasError) {
// check the type of web service
if (response.requestType == RequestType.SEARCH_FOR_TRIP) {
// acces the return here from response.result
}
} else {
String errorMsg = response.hasError ? response.errorMessage : getString(R.string.no_connection_error);
// show the error to the user
}
} catch (Exception objException) {
// show the error to the user
}
}
#Override
public Context getContext() {
// do not forgit set the context here
// if fragment replace with getAcitvity();
return this;
}
}
I am trying to properly handle Volley responses in my Android application, which loads some items from a database. Volley functions are encapsulated in the WebRequester class:
public class WebRequester extends Application {
public static final String TAG = WebRequester.class.getSimpleName();
private RequestQueue mRequestQueue;
private static WebRequester mInstance;
public WebRequester() {
mInstance = this;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public static synchronized WebRequester getInstance() {
return mInstance;
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
/* ... */
}
Another class, ItemsController, centralizes the requests to be created. In order to get the response code, I created a nested class, VolleyCallback, and set its attribute responseCode inside an overriden parseNetworkResponse() call:
public class FeedItemsController extends Application {
private String URL_GET_FEED_ITEMS = /* My URL */;
private static final String TAG = FeedItemsController.class.getSimpleName();
private ArrayList<FeedItem> feedItems;
public class VolleyRequestCallback {
public int responseCode;
public int getResponseCode() {
return responseCode;
}
public void setResponseCode(int responseCode) {
this.responseCode = responseCode;
}
}
public void loadItems() {
final VolleyRequestCallback callback = new VolleyRequestCallback();
if (feedItems == null) {
feedItems = new ArrayList<>();
Cache cache = WebRequester.getInstance().getRequestQueue().getCache();
Cache.Entry entry = cache.get(URL_GET_FEED_ITEMS);
if (entry != null) {
try {
String data = new String(entry.data, "UTF-8");
parseJsonFeed(new JSONObject(data));
} catch (JSONException | IOException e) {
e.printStackTrace();
}
}
else {
JsonObjectRequest jsonReq = new JsonObjectRequest(Request.Method.GET, URL_GET_FEED_ITEMS, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
VolleyLog.d(TAG, "Response: " + response.toString());
parseJsonFeed(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
}
) {
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
callback.setResponseCode(response.statusCode);
System.out.println("Code 1 = " + response.statusCode);
return super.parseNetworkResponse(response);
}
};
WebRequester.getInstance().addToRequestQueue(jsonReq);
}
}
System.out.println("Code 2 = " + callback.getResponseCode());
}
/* ... */
}
Then method loadItems() is called from another class. The issue is - when it enters the parseNetworkResponse() method, the resultCode is correctly set to, let's say, 200. However, when I try to reuse it outside the request overriding, it's 0 again:
Code 1 = 200
Code 2 = 0
It might be a bad implementation of a response handling, but my main question is why is the object attribute changed?
Thanks in advance
It turned out to be a not exciting bug. The call to parseNetworkResponse is asynchronous, meaning that when the first print is performed, the server had not responded yet.
I am using a global variables "GlobalVariables" in a separated class and I am try to use it in the following code but it is always gives me the error :
The method getApplication() is undefined for the type UploadPicture
I tried the following but still have error:
((GlobalVariables) this.getApplication()).set_FileUploading(false);
The qustion was already asked here but unfortunatlly all the answors didn't work with me and gave me same error! any suggestion please?
public class UploadPicture extends AsyncTask<Void, Long, Boolean> {
private DropboxAPI<?> mApi;
private String mPath;
private File mFile;
private long mFileLen;
private UploadRequest mRequest;
private Context mContext;
private String mErrorMsg;
private File outFiles;
public UploadPicture(Context context, DropboxAPI<?> api, String dropboxPath, File file) {
mContext = context.getApplicationContext();
mFileLen = file.length();
mApi = api;
mPath = dropboxPath;
mFile = file;
}
#Override
protected Boolean doInBackground(Void... params) {
try {
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + outFiles.getName();
mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(),
new ProgressListener() {
#Override
public long progressInterval() {
return 500;
}
#Override
public void onProgress(long bytes, long total) {
//publishProgress(bytes);
}
}
);
if (mRequest != null) {
mRequest.upload();
((GlobalVariables) UploadPicture.this.getApplication()).set_FileUploading(false);
return true;
}
} catch (DropboxUnlinkedException e) {
// This session wasn't authenticated properly or user unlinked
mErrorMsg = "This app wasn't authenticated properly.";
} catch (DropboxFileSizeException e) {
// File size too big to upload via the API
mErrorMsg = "This file is too big to upload";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Upload canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
}
Edit: I am adding now my "VariableGlobales" calss:
public class GlobalVariables extends Application {
private Boolean _IsIOIORunning=false;
private Boolean _FileUploading=false;
public Boolean get_IsIOIORunning()
{
return _IsIOIORunning;
}
public void set_IsIOIORunning(Boolean _IsIOIORunning)
{
this._IsIOIORunning = _IsIOIORunning;
}
public Boolean get_FileUploading()
{
return _FileUploading;
}
public void set_FileUploading(Boolean _FileUploading)
{
this._FileUploading = _FileUploading;
}
It's normal UploadPicture doesn't extend GlobalVariables but it extend AsyncTask.
That it's my "GlobalVariables "
public class AppInfo extends Application {
private static Context context;
private static String user;
public void onCreate(){
super.onCreate();
AppInfo.context = getApplicationContext();
user = null;
}
public static Context getAppContext() {return AppInfo.context;}
public static String getUser() {return user;}
public static void setUser(String user) {AppInfo.user = user;}
}
And I call it everywhere like that:
AppInfo.getUser();
Edit:
GlobalVariables should use static method and variables:
public class GlobalVariables extends Application {
private static Boolean _IsIOIORunning=false;
private static Boolean _FileUploading=false;
public static Boolean get_IsIOIORunning() {
return _IsIOIORunning;
}
public static void set_IsIOIORunning(Boolean _IsIOIORunning) {
GlobalVariables._IsIOIORunning = _IsIOIORunning;
}
public static Boolean get_FileUploading(){
return _FileUploading;
}
public static void set_FileUploading(Boolean _FileUploading){
GlobalVariables._FileUploading = _FileUploading;
}
}
Below are my service, serviceImpl and async callback interfaces. Appreciate if someone can help me understand why the submitTeam(...) isn't being called (I howeve see that isValidEmail(...) is being invoked when used). At least provide me the approach for debugging this as currently I am unable to use eclipse debugger (eclipse is not stopping at breakpoints) and the sysout/syserr statements are not being logged to the console either :-(.
#RemoteServiceRelativePath("registrationService")
public interface RegistrationService extends RemoteService
{
Boolean isValidEmail(String email);
String submitTeam(String teamName, List<Player> players);
}
public interface RegistrationServiceAsync
{
void isValidEmail(String email, AsyncCallback<Boolean> callback);
void submitTeam(String teamName, List<Player> players, AsyncCallback<String> callback);
}
public class SubmitTeamCallback implements AsyncCallback<String> {
private final Label status;
public SubmitTeamCallback(Label s) {
status = s;
}
public void onFailure(Throwable caught) {
status.setText(caught.getMessage());
}
public void onSuccess(String result) {
System.out.println("" + getClass().getName() + " : " + result);
status.setText(result);
}
}
public class RegistrationCallback implements AsyncCallback<Boolean>
{
private final Label status;
private final PlayerWidget playerWidget;
private Boolean isValidSharedFlag;
public RegistrationCallback(Label s, PlayerWidget pw, Boolean isValid)
{
status = s;
playerWidget = pw;
setIsValidSharedFlag(isValid);
}
public void onFailure(Throwable caught)
{
status.setText(caught.getMessage());
}
public void onSuccess(Boolean result)
{
if (result.equals(Boolean.FALSE))
{
playerWidget.invalidEmail();
String oldText = status.getText();
status.setText(oldText + "Please specify a valid email address for the captain.");
setIsValidSharedFlag(Boolean.FALSE);
} else
{
playerWidget.validEmail();
String newText = status.getText().replace("Please specify a valid email address for the captain.", "");
status.setText(newText);
setIsValidSharedFlag(Boolean.TRUE);
}
}
public void setIsValidSharedFlag(Boolean isValidSharedFlag)
{
this.isValidSharedFlag = isValidSharedFlag;
}
public Boolean getIsValidSharedFlag()
{
return isValidSharedFlag;
}
}
public class RegistrationServiceImpl extends RemoteServiceServlet implements
RegistrationService {
Logger logger = Logger.getLogger("");
private final Emailer emailer = new Emailer();
private final EmailValidator validator = new EmailValidator();
public Boolean isValidEmail(String email) {
return validator.validate(email);
}
public String submitTeam(String teamName, List<Player> players) {
logger.log(Level.SEVERE, "This is a test log");
System.out.println("This is a test log");
boolean emailSent = false;
for (Player p : players) {
System.out.println("Emailing to captain");
if (p instanceof Captain) {
if (!validator.validate(p.getEmail())) {
return "Please specify a valid email";
}
System.out.println("Emailing to captain");
emailSent = emailer.email(p);
}
}
if (emailSent) {
System.out.println("Email sent successfully");
return teamName
+ " has been successfully registered. Please pay the registration fee to confirm registration. Thank you.";
} else {
return "Unable to send email. Please email the team details [Team name, minimum of 6 players, captain's email address and phone number] to funpluscharity#gmail.com";
}
}
}
Below method is going to invoke the RPC calls
private void registerTeam() {
System.out.println("Received request to dubmit team");
StringBuilder statusText = new StringBuilder();
try {
Boolean isValid = true;
RegistrationServiceAsync service = (RegistrationServiceAsync) GWT
.create(RegistrationService.class);
ServiceDefTarget serviceDef = (ServiceDefTarget) service;
System.err.println(".........." + GWT.getModuleBaseURL());
serviceDef
.setServiceEntryPoint("/services/registrationService");
if (teamName.getText() == null
|| teamName.getText().length() == 0) {
isValid = false;
statusText.append("Please specify team name. ");
}
Player captain = getCaptain();
if (!atleast6PlayersAreSpecified()) {
isValid = false;
statusText.append("Please specify atleast 6 players. ");
}
if (captain == null) {
isValid = false;
statusText.append("Please designate a captain. ");
}
System.out.println("Is request valid? " + isValid);
if (isValid.equals(Boolean.TRUE)) {
System.out.println("RPC - submitTeam start ");
System.out.println("" + getPlayers());
SubmitTeamCallback callback = new SubmitTeamCallback(status);
service.submitTeam(teamName.getText(), getPlayers(),
callback);
System.out.println("RPC - submitTeam end");
} else {
status.setText(statusText.toString());
}
} catch (Exception e) {
e.printStackTrace();
System.err.println(e.getMessage());
}
}
Made some progress after adding Window.alert(...) based on #Pistol suggestion and it is going to onFailure(Throwable t) method of the SubmitTeamCallback class.
unknown.com_google_gwt_user_client_rpc_SerializationException_SerializationException__Ljava_lang_String_2V(Unknown Source)
An alternative method to debug client side code is using Window.alert(...). For example placing it in your callback onFailure() method to see caught messages for a start. Or you can use FireBug or something similar to see if the rpc-call is actually being made?
Edit :
Are you sure your Player class implements IsSerializable and have an empty constructor? Check out Serializable User-Defined Classes.
Figured this out. The POJO's should have a default constructor and the one's I am using didn't have one. GWT compiler didn't complain either. Not sure why.