When I execute a CalendarService.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer()); I get an OAuthException 401 Error Unknown authorization header.
I'm using GWT+GAE I don't know why I'm receiving this error, oauthParameters seem to be OK.
I get user login on
loginService.login
I check if I have
the authentication already on
oauthService.checkOauthTokenSecret
If not, I'll do a redirect to Google
Aproval page for GCalendar
permission
I get querystring
returned by Google and I get Access
Token and Access Token Secret and
set it to the user entity for later
use on oauthService.upgradeLogin.
And trying to get calendars on
oauthService.getPublicCalendars.
I'm using MVP pattern with mvp4g framework, sorry if is a bit confusing 0:-)
Any idea why I'm receiving 401 error? I think is something about I'm going up & down through client and server and external pages... and something is missing :-( but all parameters seem to be correctly fullfilled.
Client side
public void onStart(){
GWT.log("onStart");
loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback<LoginInfo>() {
#Override
public void onSuccess(LoginInfo result) {
Common.loginInfo = result;
if(Common.loginInfo.isLoggedIn()) {
oauthService.checkOauthTokenSecret(new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
if (result == null){
eventBus.OauthLogin();
}else{
oauthService.upgradeLogin(Window.Location.getQueryString(),Common.loginInfo, new AsyncCallback<LoginInfo>() {
#Override
public void onSuccess(LoginInfo result) {
Common.loginInfo = result;
getCitas();
}
#Override public void onFailure(Throwable caught) {
Common.handleError(caught);
}
});
}
}
#Override public void onFailure(Throwable caught) {
Common.handleError(caught);
}
});
}else{
eventBus.LoadLogin();
}
}
#Override public void onFailure(Throwable caught) {
Common.handleError(caught);
}
});
}
Server Side
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import com.google.gdata.client.authn.oauth.GoogleOAuthHelper;
import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
import com.google.gdata.client.authn.oauth.OAuthException;
import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;
import com.google.gdata.client.authn.oauth.OAuthParameters;
import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.calendar.CalendarEntry;
import com.google.gdata.data.calendar.CalendarFeed;
import com.google.gdata.util.ServiceException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.rdt.citas.client.OAuthoritzationService;
import com.rdt.citas.client.shared.LoginInfo;
public class OAuthoritzationServiceImpl extends RemoteServiceServlet
implements OAuthoritzationService {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(OAuthoritzationServiceImpl.class.getName());
private static String KEY_PARAM = "oauth_consumer_key";
private static String SECRET_PARAM = "oauth_consumer_secret";
private static String SCOPE_PARAM = "scope_calendars";
private static String CALLBACK_PARAM = "oauth_callback";
public String checkOauthTokenSecret(){
ServletContext context = this.getServletContext();
getOauthParams(context);
return (String) this.getThreadLocalRequest().getSession().getAttribute("oauthTokenSecret");;
}
public String getApprovalOAuthPageURL() throws IOException{
ServletContext context = this.getServletContext();
getOauthParams(context);
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(getFromSession(KEY_PARAM));
oauthParameters.setOAuthConsumerSecret(getFromSession(SECRET_PARAM));
oauthParameters.setScope(getFromSession(SCOPE_PARAM));
oauthParameters.setOAuthCallback(getFromSession(CALLBACK_PARAM));
GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(new OAuthHmacSha1Signer());
try {
oauthHelper.getUnauthorizedRequestToken(oauthParameters);
String approvalPageUrl = oauthHelper.createUserAuthorizationUrl(oauthParameters);
String oauthTokenSecret = oauthParameters.getOAuthTokenSecret();
this.getThreadLocalRequest().getSession().setAttribute("oauthTokenSecret", oauthTokenSecret);
return approvalPageUrl;
} catch (OAuthException e) {
log.log(Level.WARNING,e.toString());
return "";
} finally{
}
}
public LoginInfo upgradeLogin(String queryString, LoginInfo login){
// receiving '?key1=value1&key2=value2
queryString = queryString.substring(1, queryString.length());
String k = getFromSession(KEY_PARAM);
String s = getFromSession(SECRET_PARAM);
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(k);
oauthParameters.setOAuthConsumerSecret(s);
String oauthTS = (String) this.getThreadLocalRequest().getSession().getAttribute("oauthTokenSecret");//oauthParameters.getOAuthTokenSecret();
oauthParameters.setOAuthTokenSecret(oauthTS);
GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(new OAuthHmacSha1Signer());
oauthHelper.getOAuthParametersFromCallback(queryString,oauthParameters);
login.setQueryStringTokens(queryString);
login.setAccessTokenSecret(oauthTS);
try {
String accesToken = oauthHelper.getAccessToken(oauthParameters);
login.setTokenSecret(accesToken);
} catch (OAuthException e) {
log.log(Level.WARNING,e.toString());
}
return login;
}
public ArrayList<String> getPublicCalendars(String accessToken, String accessTokenSecret){
ArrayList<String> result = new ArrayList<String>();
CalendarFeed calendarResultFeed = null;
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(getFromSession(KEY_PARAM));
oauthParameters.setOAuthConsumerSecret(getFromSession(SECRET_PARAM));
oauthParameters.setOAuthToken(accessToken);
oauthParameters.setOAuthTokenSecret(accessTokenSecret);
oauthParameters.setOAuthType(OAuthParameters.OAuthType.THREE_LEGGED_OAUTH);
oauthParameters.setScope(getFromSession(SCOPE_PARAM));
CalendarService myService = new CalendarService("exampleCo-exampleApp-1");
try {
myService.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer());
URL calendarFeedUrl = new URL("https://www.google.com/calendar/feeds/default/owncalendars/full");
calendarResultFeed = myService.getFeed(calendarFeedUrl, CalendarFeed.class);
} catch (OAuthException e) {
log.info("OAuthException");
log.log(Level.WARNING,e.toString());
e.printStackTrace();
} catch (MalformedURLException e) {
log.info("MalformedURLException");
log.log(Level.WARNING,e.toString());
e.printStackTrace();
} catch (IOException e) {
log.info("IOException");
log.log(Level.WARNING,e.toString());
e.printStackTrace();
} catch (ServiceException e) {
log.info("ServiceException");
log.log(Level.WARNING,e.toString());
e.printStackTrace();
}
if (calendarResultFeed != null && calendarResultFeed.getEntries() != null) {
for (int i = 0; i < calendarResultFeed.getEntries().size(); i++) {
CalendarEntry entry = calendarResultFeed.getEntries().get(i);
result.add(entry.getTitle().getPlainText());
}
}
return result;
}
private void getOauthParams(ServletContext context) {
this.getThreadLocalRequest().getSession()
.setAttribute(KEY_PARAM, context.getInitParameter(KEY_PARAM));
this.getThreadLocalRequest().getSession()
.setAttribute(SECRET_PARAM, context.getInitParameter(SECRET_PARAM));
this.getThreadLocalRequest().getSession()
.setAttribute(SCOPE_PARAM, context.getInitParameter(SCOPE_PARAM));
this.getThreadLocalRequest().getSession()
.setAttribute(CALLBACK_PARAM, context.getInitParameter(CALLBACK_PARAM));
}
private String getFromSession(String param){
return (String) this.getThreadLocalRequest().getSession().getAttribute(param);
}
}
I have recently been working with oAuth. Inside upgradeLogin(...) when you are upgrading to an access token you are not fetching the respective access token secret.
The access token secret following the getAccessToken() request is different to the access token secret before the request. You are currently setting the access token secret (via login.setAccessTokenSecret(oauthTS)), it is the pre-updated access token secret value you are using. You need to set it to the access token secret value returned after the update request:
String accesToken = oauthHelper.getAccessToken(oauthParameters);
String accesTokenSecret = oauthParameters.getOAuthTokenSecret();
login.setTokenSecret(accesToken);
login.setAccessTokenSecret(accesTokenSecret);
You also probably want to store this updated token/secret pair somewhere. It is this value of access token secret that should then to be used inside getPublicCalendars(...) in the line:
oauthParameters.setOAuthTokenSecret(accessTokenSecret);
The post update access token/secret pair is long-lived and can therefore be re-used (without needing to update it again) until such time as it is revoked.
Incidentally I found the oAuth Playground Tool useful in diagnosing my problems.
I hope this helps,
Related
This is our custom component class, in which I want to get the data from one core and search data into another core and use facet query and show in descending order.
means suppose we get t-shirt name from one core and same t-shirt name we will search it into another core and display the over all result with facet query
package com.shop.component;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class CustomQueryComponent extends SearchComponent{
private static final Logger LOG = LoggerFactory.getLogger(CustomQueryComponent.class);
#Override
public void prepare(ResponseBuilder responseBuilder) throws IOException {
LOG.info("prepare method of CustomQueryComponent");
}
#Override
public void process(ResponseBuilder responseBuilder) throws IOException {
LOG.info("process method of CustomQueryComponent");
}
#Override
public String getDescription() {
return "CustomQueryComponent";
}
}
You can use the org.apache.solr.client.solrj.embedded.EmbeddedSolrServer in your own search component to fire off a Solr-query. In my example I am doing a call to the same core, so the only thing left is to figure out how it can be done to a different core:
#Override
public void prepare(final ResponseBuilder responseBuilder) throws IOException
{
SolrParams params = responseBuilder.req.getParams();
SolrClient solrClient = new EmbeddedSolrServer(responseBuilder.req.getCore());
ModifiableSolrParams subQueryParams = new ModifiableSolrParams(params);
if( subQueryParams.get("rows").equals("0"))//needed to prevent an infinite loop
{
return;
}
subQueryParams.set("rows",0);
subQueryParams.set("facet",true);
subQueryParams.set("facet.field", PIM_FIELDS);
try
{
QueryResponse response = solrClient.query(subQueryParams);
FacetField pimFields = response.getFacetField(PIM_FIELDS);
List<FacetField.Count> values = pimFields.getValues();
ModifiableSolrParams newParams = new ModifiableSolrParams(params);
for (final FacetField.Count value : values)
{
newParams.add("facet.field", value.getName());
value.getFacetField().getName();
}
newParams.set("facet", true);
newParams.set("facet.mincount",1);
responseBuilder.req.setParams(newParams);
}
catch (SolrServerException e)
{
throw new RuntimeException(e);
}
}
You can reach other collections running on the same solr-instance via the coreContainer on the req.getCore(), as I do in this example:
private SolrDocumentList getEntries(final ResponseBuilder responseBuilder) throws IOException
{
ModifiableSolrParams unitQueryParams = new ModifiableSolrParams();
unitQueryParams.add("q","*:*");
unitQueryParams.add("rows","300");
SolrCore localDoc = responseBuilder.req.getCore().getCoreContainer().getCore("webshop_classificationattributeunit");
EmbeddedSolrServer unitQueryClient = new EmbeddedSolrServer(localDoc);
QueryResponse unitResponse;
try
{
unitResponse = unitQueryClient.query(unitQueryParams);
}
catch (SolrServerException e)
{
throw new RuntimeException(e);
}
return unitResponse.getResults();
}
The application's password recovery functionality sends an email with a link to a page where a user sets a new password. This link does not expire if not used, which makes it possible for an attacker to re-use it in order to compromise an account. How to make a reset password link to expire in 24 hours of sending the user an email?
Can someone tell me what is the approach I should take to solve this issue?
package com.www.actions;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import com.lang.EncryptionUtil;
import com.www.crm.CrmUser;
import com.www.customer.dao.CustomerUtils;
import com.www.interceptors.SessionManager;
import com.www.services.AmsCustomerService;
import com.raleys.www.services.IAmsCustomerService;
public class PasswordUpdateAction extends BaseAction {
/** Comment for <code>serialVersionUID</code> */
private static final long serialVersionUID = 1L;
private final Logger logger = Logger.getLogger(PasswordUpdateAction.class);
private String password1 = null;
private String password2 = null;
private final SessionManager sessionManager;
public PasswordUpdateAction(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
#Override
public String execute() {
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = ServletActionContext.getRequest().getSession();
IAmsCustomerService amsCustomerService = new AmsCustomerService();
CrmUser crmUser = this.sessionManager.getCrmUser(session);
if (crmUser == null) {
request.setAttribute("errorMsg", LOGIN_MSG);
request.setAttribute("sessionErrorMsg", LOGIN_MSG);
return ERROR;
}
if (StringUtils.isBlank(this.sessionManager.getCredentials(session))) {
request.setAttribute("errorMsg", LOGIN_MSG);
request.setAttribute("sessionErrorMsg", LOGIN_MSG);
return ERROR;
}
String errorMsg = null;
try {
errorMsg = validateForm();
if (StringUtils.isBlank(errorMsg)) {
String encryptedPassword = EncryptionUtil.encodePassword(getPassword1(), "MD5");
crmUser.setPassword(encryptedPassword.toUpperCase());
int success = amsCustomerService.updateCrmUserLocally(crmUser);
if (success == 1) {
request.setAttribute("successMsg", "Your Password Has Been Updated Successfully! ");
return SUCCESS;
} else {
this.logger.error("Error Updating crmUser in Local DB. ");
errorMsg = "Unexpected error occur while updating your password, please try again.";
}
}
} catch (Exception ex) {
this.logger.error("Error, " + ex.getMessage());
errorMsg = "Unexpected error occur while updating your password, please try again.";
}
request.setAttribute("errorMsg", errorMsg);
return ERROR;
}
private String validateForm() {
return CustomerUtils.validatePasswords(getPassword1(), getPassword2());
}
public String getPassword1() {
return this.password1;
}
public void setPassword1(String password1) {
this.password1 = password1;
}
public String getPassword2() {
return this.password2;
}
public void setPassword2(String password2) {
this.password2 = password2;
}
}
Save the Date when the link expires along with the link / link key. When the user tries to change his password using that link, check that the expiry date is in the future.
. Hi, as a young android developer i was looking at a way to get a JSON response from a server.
I started looking at AsyncTask but i not feeling comfortable to code an AsyncTask for each time i needed to ask a WebService.
Then i started to code a class (extends AsyncTask) that query an URL (POST or GET) and provide a callback containing the response from the server.
I wanted to have some feedback, is it really useful, and not an useless overlay of an AsyncTask cause i missed understand something at the beginning.
The more i code it, the more i doubt.
Thanks in advance for your feedback.
Here's the code i use to query a server with my class :
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put("address", "sidney");
parameters.put("sensor", "false");
WebServiceAsyncTask asyncWS = new WebServiceAsyncTask(MainActivity.this);
asyncWS.setParameters(parameters);
asyncWS.execute(
"http://maps.googleapis.com/maps/api/geocode/json",
WebServiceAsyncTask.GET,
new WebServiceAsyncTaskCallback() {
#Override
void callbackMethod(String result) {
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show();
}
}
);
Here's the code of my WebServiceAsyncTask :
import android.app.ProgressDialog;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Anthony Raymond
*/
public class WebServiceAsyncTask extends AsyncTask<Object, String, String> {
public static final String GET = "GET";
public static final String POST = "POST";
private static final String PROGRESS_TEXT_PREPARING = "Preparing request";
private static final String PROGRESS_PERCENT_PREPARING = "25";
private static final String PROGRESS_TEXT_CONNECTION_SERVER = "Connecting to the server";
private static final String PROGRESS_PERCENT_CONNECTION_SERVER = "50";
private static final String PROGRESS_TEXT_PARSING = "Parsing received data";
private static final String PROGRESS_PERCENT_PARSING = "75";
private static final String PROGRESS_TEXT_END = "Process ended";
private static final String PROGRESS_PERCENT_END = "100";
private Context context;
private HashMap<String, String> mData = new HashMap<String, String>();
private ProgressDialog progressDialog;
private WebServiceAsyncTaskCallback callbackClass;
/**
* If a Context is passed, a ProgressDialog will be displayed
* NEED TO PASS Context LIKE THIS :
* MyActivity.this
* DO NOT USE getApplicationContext()
* #param applicationContext
*/
public WebServiceAsyncTask(Context applicationContext)
{
this.context = applicationContext;
}
/**
* Create a WebServiceAsyncTask.
* Usage : add request parameter by passing an HashMap<String, String> with the setParameter Method, then call
* .execute(String url, WebServiceAsyncTask constant (GET or SET), WebServiceAsyncTaskCallback callback)
* exemple :
* HashMap<String, String> parameters = new HashMap<String, String>();
* parameters.put("address", "Sidney");
* parameters.put("sensor", "false");
* WebServiceAsyncTask asyncWS = new WebServiceAsyncTask(MainActivity.this);
* asyncWS.setParameters(parameters);
* asyncWS.execute(
* "http://maps.googleapis.com/maps/api/geocode/json",
* WebServiceAsyncTask.GET,
* new WebServiceAsyncTaskCallback() {
* #Override
* void callbackMethod(String result) {
* Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show();
* }
* }
* );
*/
public WebServiceAsyncTask()
{
this.context = null;
}
private void prepareProgressDialog()
{
if (this.context != null)
{
this.progressDialog = new ProgressDialog(this.context);
this.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.progressDialog.setCancelable(true);
this.progressDialog.setTitle("Please Wait...");
this.progressDialog.setMessage(PROGRESS_TEXT_PREPARING);
this.progressDialog.setProgress(Integer.parseInt(PROGRESS_PERCENT_PREPARING));
}
}
private String getPostResponse(String url)
{
byte[] result;
String str = "";
HttpClient client = new DefaultHttpClient();
HttpPost http = new HttpPost(url);
// set up post data
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>();
for (String key : this.mData.keySet()) {
nameValuePair.add(new BasicNameValuePair(key, this.mData.get(key)));
}
UrlEncodedFormEntity urlEncodedFormEntity;
try
{
urlEncodedFormEntity = new UrlEncodedFormEntity(nameValuePair);
http.setEntity(urlEncodedFormEntity);
this.publishProgress(PROGRESS_TEXT_CONNECTION_SERVER, PROGRESS_PERCENT_CONNECTION_SERVER);
HttpResponse response = client.execute(http);
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpURLConnection.HTTP_OK)
{
this.publishProgress(PROGRESS_TEXT_PARSING, PROGRESS_PERCENT_PARSING);
result = EntityUtils.toByteArray(response.getEntity());
str = new String(result, HTTP.UTF_8);
}
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
return str;
}
private String getGetResponse(String url)
{
byte[] result;
String str = "";
HttpClient client = new DefaultHttpClient();
try
{
// set up get data and URL
Uri.Builder uri = Uri.parse(url).buildUpon();
for (String key : this.mData.keySet()) {
uri.appendQueryParameter(key, this.mData.get(key));
}
HttpGet http = new HttpGet(String.valueOf(uri));
this.publishProgress(PROGRESS_TEXT_CONNECTION_SERVER, PROGRESS_PERCENT_CONNECTION_SERVER);
HttpResponse response = client.execute(http);
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpURLConnection.HTTP_OK)
{
this.publishProgress(PROGRESS_TEXT_PARSING, PROGRESS_PERCENT_PARSING);
result = EntityUtils.toByteArray(response.getEntity());
str = new String(result, HTTP.UTF_8);
}
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
return str;
}
public void setParameters(HashMap<String, String> httpRequestParameters)
{
this.mData = httpRequestParameters;
}
#Override
protected String doInBackground(Object... params)
{
// Ensure that we got, URL, http method and Callback
if (params.length != 3)
{
this.cancel(true);
}
else
{
if ((params[2] instanceof WebServiceAsyncTaskCallback))
{
this.callbackClass = ((WebServiceAsyncTaskCallback)params[2]);
}
else
{
this.cancel(true);
}
try {
URL url = new URL((String)params[0]);
} catch (MalformedURLException e) {
this.callbackClass.onError("First param must be a valid URL. (" + params[0] + " given)");
this.cancel(true);
}
if (!((String)params[1]).equals(POST) && !((String)params[1]).equals(GET))
{
this.callbackClass.onError("Second parameters must be " + this.getClass().getName() + " POST or GET constant");
this.cancel(true);
}
}
String str = "";
//IS OUR REQUEST A POST
if (params.length > 1)
{
if (((String)params[1]).toUpperCase().equals(WebServiceAsyncTask.POST))
{
str = getPostResponse(((String)params[0]));
}
else if(((String)params[1]).toUpperCase().equals(WebServiceAsyncTask.GET)) //THEN GET
{
str = getGetResponse(((String)params[0]));
}
}
return str;
}
#Override
protected void onPostExecute(String result)
{
this.mData = null;
if (this.context != null)
{
this.publishProgress(PROGRESS_TEXT_END, PROGRESS_PERCENT_END);
this.progressDialog.dismiss();
}
if (this.callbackClass != null)
{
this.callbackClass.callbackMethod(result);
}
}
#Override
protected void onPreExecute()
{
if (this.context != null)
{
this.prepareProgressDialog();
this.progressDialog.show();
}
}
#Override
protected void onProgressUpdate(String... values) {
if (this.context != null)
{
this.progressDialog.setMessage(values[0]);
this.progressDialog.setProgress(Integer.parseInt(values[1]));
}
}
}
/**
* Allow to easily get the server response
*/
abstract class WebServiceAsyncTaskCallback{
/**
* Return the server response as String
* #param result server response as a String
*/
abstract void callbackMethod(String result);
/**
* This method is design to report simple errors for development phase.
* #param errMessage contains error message
*/
protected void onError(String errMessage){};
;
}
Your use of AsyncTask appears appropriate. As you may be aware.. for network communications you must use AsyncTask or your own thread (extend HandlerThread.)
If your app is frequently calling AsyncTask or is executing simultaneous AsyncTask then creating your own thread will be more efficient (all AsyncTask requests use a single thread in API 13 and up.)
I'm unfamiliar with your app and how it functions.. do your users require the dialogs and status feedback for thses background network transmissions?
Can I just point out that, because you are not doing this in a Service, your remote query stands every chance of being killed, as soon your Activity is hidden. You have, essentially, rewritten IntentService... except that your version will get killed and the version the framework provides, free, will not
IntentService, FTW
I am new to J2ME and am building a mobile application where users can register, login and be presented with some member only screen where they can perform some operations.
(I am into web development, hence kindly correct me where I use a web approach. Also, I clearly understand basic java concepts but have not built a mobile app before)
So far, I have created the first screen with a login form containing a username and password textbox, and Login and Exit buttons.
The problems I am currently facing are:
How can I provide access to Register, Login and Exit at the same time (it seems the phone can only have two buttons at a time). Do I provide them as command buttons or normal 'web like buttons that appear on page'? Kindly tell me how for any of the options that seems appropriate.
How do I send and receive data over http in the mobile application? Sample code will be appreciated.
How do I manage the different screens? In web development, I simply create pages and link them up. In this case, how can I display a register screen when the register button is pressed? The home screen when login is successful? or an error message when unsuccessful?
Do I have different functions that dynamically generates the screens? and I call them each time when the screens are requested?
Simple samples will be highly appreciated.
In J2ME,
You have the display object which determines what is shown on the screen. There are something which can be displayed. For example a Form, List, Textbox etc. Therefore what you can do is you can create the following displays
public class IndexScreen extends List implements CommandListener {
//This will contain the options
//1. Register
//2. Login
//3. Exit
}
public class RegsterScreen extends Form implements CommandListener {
//This will contain register fields and submit cancel command buttons
}
public class LoginScreen extends Form implements CommandListener {
//This will contain Login specific controls
}
Now once these displayable objects are ready you can keep changing the display on some events like click of a command button.
public void commandAction(Command c, Displayable d) {
if (c == OK) {
nextScreen = new RegisterScreen();
display.setCurrent(nextScreen);
}
if (c == BACK) {
display.setCurrent(prevScreen);
}
For sending and receiving data the following may help....
package madmin.client;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.Display;
import madmin.res.Globals;
public class ClientRequest {
private Client client;
private Display display;
private String requestServlet;
private String requestCode;
private String requestId;
private String userId;
private String url;
private String response;
private String parameterOne;
public ClientRequest() {
}
public boolean sendRequest() {
boolean result = false;
userId = Globals.getUserId();
url = Globals.getURL() + requestServlet + "?requestCode=" + requestCode + "&requestId=" + requestId + "&userId=" + userId + "&clientIP=" + client.getIpAddress() + "&clientHostName=" + client.getHostname() + "¶meterOne=" + parameterOne;
System.out.println("User Id value in ClientRequest " + userId);
System.out.println("Start HTTP Connection");
HttpConnection connection = null;
InputStream inputstream = null;
try {
connection = (HttpConnection) Connector.open(url);
connection.setRequestMethod(HttpConnection.GET);
connection.setRequestProperty("Content-Type", "//text plain");
connection.setRequestProperty("Connection", "close");
System.out.println("Status Line COde: "+ connection.getResponseCode());
System.out.println("Status Line Message: "+ connection.getResponseMessage());
if(connection.getResponseCode()==HttpConnection.HTTP_OK){
inputstream = connection.openInputStream();
int length = (int) connection.getLength();
if(length!=-1){
byte incomingData[] = new byte[length];
inputstream.read(incomingData);
response = new String(incomingData);
}
else {
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
int ch;
while((ch = inputstream.read())!=-1){
bytestream.write(ch);
}
response = new String(bytestream.toByteArray());
bytestream.close();
}
System.out.println("Response:" + response.trim());
if(response.trim().equals("Request Submitted Successfully")){
result = true;
}
else{
result = false;
}
}
connection.close();
if(inputstream!=null)inputstream.close();
}
catch(Exception e) {
e.printStackTrace();
}
finally {
if(inputstream!=null){
try{
inputstream.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
return result;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public Display getDisplay() {
return display;
}
public void setDisplay(Display display) {
this.display = display;
}
public String getRequestCode() {
return requestCode;
}
public void setRequestCode(String requestCode) {
this.requestCode = requestCode;
}
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
public String getRequestServlet() {
return requestServlet;
}
public void setRequestServlet(String requestServlet) {
this.requestServlet = requestServlet;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getParameterOne() {
return parameterOne;
}
public void setParameterOne(String parameterOne) {
this.parameterOne = parameterOne;
}
}
and....
package madmin.client;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import madmin.res.Globals;
public class ClientResponse {
private String response;
public String getResponse(String requestId) {
System.out.println("Start HTTP Connection");
HttpConnection connection = null;
InputStream inputstream = null;
response = "";
try{
connection = (HttpConnection) Connector.open( Globals.getURL() + "ResponseServlet?requestId=" + requestId);
connection.setRequestMethod(HttpConnection.GET);
connection.setRequestProperty("Content-Type", "//text plain");
connection.setRequestProperty("Connection", "close");
System.out.println("Status Line COde: "+ connection.getResponseCode());
System.out.println("Status Line Message: "+ connection.getResponseMessage());
if(connection.getResponseCode()==HttpConnection.HTTP_OK){
inputstream = connection.openInputStream();
int length = (int) connection.getLength();
if(length!=-1){
byte incomingData[] = new byte[length];
inputstream.read(incomingData);
response = new String(incomingData);
}
else {
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
int ch;
while((ch = inputstream.read())!=-1){
bytestream.write(ch);
}
response = new String(bytestream.toByteArray());
bytestream.close();
}
System.out.println("Response:" + response.trim());
connection.close();
if(inputstream!=null)inputstream.close();
}
}
catch(Exception e){
e.printStackTrace();
}
return response;
}
}
edited:
something like this
public class MenuScreen extends List implements CommandListener{
public MenuScreen() {
append("Register", null);
append("Login", null);
append("Forgot password", null);
select = new Command("Select", Command.OK, 1);
addCommand(select);
setCommandListener(this);
}
}
public void commandAction(Command command, Displayable display) {
if(command==List.SELECT_COMMAND){
String menuItem = this.getString(menuIndex);
}
if(command==select){
if( menuItem.equals("Register"))
display.setCurrent(new RegisterScreen())
}
}
I have this error:
WARNING: Authentication error: Unable to respond to any of these challenges: {}
Exception : No authentication header information
I am using GWT with eclipse.
I really don't know what's wrong in my code.
Any help would be appreciated.
Thanks in advance.
Client side EntryPoint class:
private static final String GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/auth";
private static final String GOOGLE_CLIENT_ID = "xxxxxxx.apps.googleusercontent.com";
private static final String CONTACTS_SCOPE = "https://www.google.com/m8/feeds";
private static final Auth AUTH = Auth.get();
public void onModuleLoad() {
final AuthRequest req = new AuthRequest(GOOGLE_AUTH_URL, GOOGLE_CLIENT_ID).withScopes(CONTACTS_SCOPE);
AUTH.login(req, new Callback<String, Throwable>() {
public void onSuccess(String token) {
ABASession.setToken(token);
}
public void onFailure(Throwable caught) {
Window.alert("Error:\n" + caught.getMessage());
}
});
}
I store the token in a class that I will use later.
Server side: ContactServiceImpl (RPC GAE procedure)
//The token stored previously is then passed through RPC
public List printAllContacts(String token) {
try {
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey("My consumer key");
oauthParameters.setOAuthConsumerSecret("My consumer secret");
PrivateKey privKey = getPrivateKey("certificate/akyosPrivateKey.key");
OAuthRsaSha1Signer signer = new OAuthRsaSha1Signer(privKey);
ContactsService service = new ContactsService("XXX");
service.setProtocolVersion(ContactsService.Versions.V3);
oauthParameters.setOAuthToken(token);
service.setOAuthCredentials(oauthParameters, signer);
// Request the feed
URL feedUrl = new URL("http://www.google.com/m8/feeds/contacts/default/full?xoauth_requestor_id=xxx.yyy#gmail.com");
ContactFeed resultFeed = service.getFeed(feedUrl, ContactFeed.class);
for (ContactEntry entry : resultFeed.getEntries()) {
for (Email email : entry.getEmailAddresses()) {
contactNames.add(email.getAddress());
}
}
return contactNames;
} catch (Exception e) {
System.err.println("Exception : " + e.getMessage());
}
return null;
}
set the scope
oauthParameters.setScope("http://www.google.com/m8/feeds/contacts/default/full");