Timeout while fetching for remoteApi GAE - google-app-engine

I'm using Java to implement remoteAPi in Google App Engine (GAE) by following this tutorial:
https://developers.google.com/appengine/docs/java/tools/remoteapi
but after configuring at web.xml, I use the following codes to insert new entity to local datastore:
String username = "myusername";
String password = "mypassword";
RemoteApiOptions options = new RemoteApiOptions()
.server("localhost", 8888)
.credentials(username, password);
RemoteApiInstaller installer = new RemoteApiInstaller();
installer.install(options);
try {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
System.out.println("Key of new entity is " +
ds.put(new Entity("Hello Remote API!")));
} finally {
installer.uninstall();
}
but error has occured:
Problem accessing /remoteApi/index. Reason:
Timeout while fetching: http://localhost:8888/remote_api
I viewed on debug and know that it caused by : "installer.install(options);" statement.
How can I solve this? Increase the socket time out ?
Thank in advance !

i did it in both local and also deployed apps.following code may help you.
remember the code must be write in RPC
i used GWT 2.4,JRE 1.7 and GAE 1.7.2.
put GAE Remote Api in WEB-INF/lib
web.xml
<servlet>
<display-name>Remote API Servlet</display-name>
<servlet-name>RemoteApiServlet</servlet-name>
<servlet-class>com.google.apphosting.utils.remoteapi.RemoteApiServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>RemoteApiServlet</servlet-name>
<url-pattern>/remote_api</url-pattern>
</servlet-mapping>
XyzServiceImpl.java
#Override
public String callGaeRemote() {
RemoteApiInstaller installer = null;
List<Entity> allEntities = null;
String response = null;
try {
RemoteApiOptions options = new RemoteApiOptions().server(
"localhost", 8888).credentials(
"username", "password");
installer = new RemoteApiInstaller();
installer.install(options);
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
System.out.println("Key of new entity is " +
ds.put(new Entity("Hello Remote API!")));
response = "Success";
} catch (IOException e) {
e.printStackTrace();
}
finally {
installer.uninstall();
}
return response;
}

Related

Solr basic authentication without setting credentials for each request

Currently I am using SOLR basic authentication feature on my SOLR cloud using Solrj library. According to documentation and only way I found, the code looks like this -
SolrRequest<QueryResponse> req = new QueryRequest(solrQuery);
req.setBasicAuthCredentials("admin", "foobar");
QueryResponse rsp = req.process(solrClient, liveStreamCollection);
documentList = rsp.getResults();
I am wondering if there is a way to avoid setBasicAuthCredentials for each request and perform it only once per session on solrClient?
Edit
Above approach worked both for SolrClient and SolrCloudClient (both core and collection). To avoid passing basic credentials for each request, I tried to build and use a HttpClient like this.
AuthScope authScope = new AuthScope("192.168.x.x", 8983);
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("admin", "foobar");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(authScope, creds);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.addInterceptorFirst(new PreemptiveAuthInterceptor());
builder.setDefaultCredentialsProvider(credsProvider);
CloseableHttpClient httpClient = builder.build();
solrClient = new HttpSolrClient("http://192.168.x.x:8983/solr/", httpClient);
And the PreemptiveAuthInterceptor class:
static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
#Override
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it preemptively
if (authState.getAuthScheme() == null) {
CredentialsProvider credsProvider = (CredentialsProvider)
context.getAttribute(HttpClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
Credentials creds = credsProvider.getCredentials(authScope);
if(creds == null){
}
authState.update(new BasicScheme(), creds);
}
}
}
This worked for a single machine Solr core but I don't know how to use this with Solr cloud(passing Zookeeper hosts etc). Any idea?
Thanks in advance!

Proper way to post to a servlet on Google App Engine from a Java client application

I have deployed an to App Engine. I setup SSL, and associated it with a custom domain. When I was developing the app locally, sending to a servlet via http://localhost:8080/servlet, worked as expected, but when I deploy it to App Engine, I have yet to get the appropriate result. I've tried many things, and the response codes I keep getting are either 404 or 500.
I startied with a simple HTTPUrlConnection and DataOutputstream to send a JSON to the servlet, and get an appropriate response. Like so:
URL url;
HttpURLConnection connection = null;
try {
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("custom-Header", "XYZ");
connection.setRequestProperty("Content-Length", Integer.toString(urlParameters.length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
//Send request
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.write(urlParameters);
wr.flush ();
wr.close ();
//Get Response
BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuffer response = new StringBuffer();
while((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
}
finally {
if(connection != null) {
connection.disconnect();
}
}
This works locally.
I've now tried Apache Common's HttpAsyncClient, to check if it maybe a timing issue:
final ResponseObject responseObject = new ResponseObject(); //my simple POJO
try(CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
.setSSLStrategy(sslSessionStrategy)
.build()) {
httpclient.start();
HttpPost post = new HttpPost(url);
post.setHeader("Content-Type", "application/json");
post.setHeader("custom-Header", "XYZ");
post.setHeader("Content-Language", "en-US");
HttpEntity entity = new ByteArrayEntity(urlParameters);
post.setEntity(entity);
final CountDownLatch latch1 = new CountDownLatch(1);
httpclient.execute(post, new FutureCallback<HttpResponse>() {
public void completed(final HttpResponse response) {
int status = response.getStatusLine().getStatusCode();
if (status >= 200 && status < 300) {
HttpEntity entity = response.getEntity();
try {
responseObject.message = entity != null ? EntityUtils.toString(entity) : null;
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
responseObject.exception = new ClientProtocolException("Unexpected response status: " + status);
}
latch1.countDown();
}
public void failed(final Exception ex) {
responseObject.exception = ex;
latch1.countDown();
}
public void cancelled() {
latch1.countDown();
}
});
latch1.await();
if(responseObject.exception != null) {
throw responseObject.exception;
} else {
return responseObject.message;
}
}
This also works locally, but when trying to reach AppEngine, still no go.
Here's my simple web.xml:
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>my.servlet.package.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>everything</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<welcome-file-list>
<welcome-file>home.jsp</welcome-file>
</welcome-file-list>
Locally, I post to http://localhost:8080/login. As for App Engine, I posted to the ff:
https://myapp.appspot.com/login
https://myapp.customdomain.com/login
I've tried changing up the url-pattern. I started with /login, then did login, then explicitly tried the both App Engine and custom domain urls (i.e. myapp.appspot.com/login and myapp.mydomain.com/login). I also tried having an actual jsp or html page to post to, after trying not having an actual page associated with the servlet i.e. login.jsp or login.html.
When I used HttpAsyncClient (my choice due to SSLContext), the best result I got was the HTML of the page associated with the servlet, but never the response I need from the Servlet.
Any ideas?
Found the answer on one of Google Cloud Platform's scattered docs:
https://cloud.google.com/appengine/docs/standard/java/how-requests-are-handled
https://cloud.google.com/appengine/docs/standard/java/how-requests-are-routed
Basically, you'll have to prepend your project's appspot url e.g. myapp.appspot.com, with the version ID of any actively serving instance of your app. You can find such IDs under the Versions page of your App Engine console. For example: https://versionId.myapp.appspot.com.

openID login (on localhost) at google app engine

I've written openID login for google App engine.
static {
openIdProviders = new HashMap<String, String>();
openIdProviders.put("Google", "https://www.google.com/accounts/o8/id");
openIdProviders.put("Yahoo", "yahoo.com");
}
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser(); // or req.getUserPrincipal()
Set<String> attributes = new HashSet();
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
if (user != null) {
out.println("Hello <i>" + user.getNickname() + "</i>!");
out.println("[sign out]");
} else {
out.println("Sign in at: ");
for (String providerName : openIdProviders.keySet()) {
String providerUrl = openIdProviders.get(providerName);
String loginUrl = userService.createLoginURL(req.getRequestURI(), null, providerUrl, attributes);
out.println("[" + providerName+ "] ");
}
}
}
everything works very well when I deploy my app. No problems.
after choosing openID provider, I'm redirected to that page:
sample.appspot.com/_ah/login_redir?claimid=[OPen ID provider]=[my sample page]/_ah/login_required
that's my servlet.
<servlet>
<servlet-name>Authorization</servlet-name>
<servlet-class>ge.eid.test.Authorization</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Authorization</servlet-name>
<url-pattern>/_ah/login_required</url-pattern>
</servlet-mapping>
ok. everything is fine! but, when I run the sampe app at localhost, I have another redirection URL:
http://localhost:8888/_ah/login?continue=/F_ah/Flogin_required
so I do not have OpenID login. I have something like that:
question 1) How to create openID login at localhost too.
This is a normal behaviour, because on localhost you might want to try many different accounts and it would be a mess if you had to actually login every time with a real one. So when on localhost you can just simulate an OpenID user just by providing any email you want and checking if you want to be an admin or not.

Javamail Configuration clarification

Through my application using Javamail API if I want to send email between any two external email addresses say gmail->yahoo or yahoo->gmail or any other email account without using authentication mechanism how should I configure mail.smtp.host property?
What is the correct way of configuring javamail properties for sending emails between any two external email addresses ?
Sample code to send mail is given below:
Session session = Session.getDefaultInstance(new Properties(),null);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("test#gmail.com"));
InternetAddress[] toAddress = {new InternetAddress("test#yahoo.com")};
message.setRecipients(Message.RecipientType.TO, toAddress);
message.setSubject("test mail"); message.setText("test body");
Transport.send(message);
Most public mail servers require authentication. If you want to do it without authentication, you'll need to run your own mail server.
This is for gmail, try it. You need mail.jar
public static void main(String[] args) {
final String username = "yourId#gmail.com";
final String password = "your-pwd";
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");
Session session = Session.getInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("yourId#gmail.com"));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse("some-mail#gmail.com"));
message.setSubject("A Mail Subject");
message.setText("Hey I'm sending mail using java api");
Transport.send(message);
System.out.println("Done");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
Edit :
Link to download Java mail Api along with mail.jar

Accessing oauth protected resource on Google App Engine

I'm trying to access an OAuth-protected resource on Google App Engine using a Java/Groovy client. However the authentication is not working and my GET requests are just bringing back the Google Accounts login page HTML.
I get the same results with HTTPBuilder/signpost and with google-oauth-java-client.
Here's what I've done:
Set up an OAuth provider as described in http://ikaisays.com/2011/05/26/setting-up-an-oauth-provider-on-google-app-engine/
Created a 'hello world' servlet (actually a Gaelyk groovlet) mapped to http://<my-app>.appspot.com/rest/hello
Deployed the servlet to gae and confirmed I can GET via a browser.
Added a security constraint to my web.xml and redeployed.
<security-constraint>
<web-resource-collection>
<web-resource-name>Rest</web-resource-name>
<url-pattern>/rest/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
Confirmed that a browser GET requires a Google Accounts login and that after login I can access the servlet.
Did the 3-legged OAuth dance as described in http://groovy.codehaus.org/modules/http-builder/doc/auth.html to get the access and client secret tokens.
Use the tokens in a RESTClient as follows (following instructions in the link above)
def client = new RESTClient('http://<my-app>.appspot.com' )
def consumerKey = <my consumer key>
def consumerSecret = <my consumer secret>
def accessToken = <my access token>
def secretToken = <my secret token>
client.auth.oauth consumerKey, consumerSecret, accessToken, secretToken
def resp = client.get(path:'/rest/hello')
assert resp.data == 'Hello world'
The assert fails since the response is the Google Accounts login page.
I get the same behaviour when using google-oauth-java-client.
I've been through the process above several times, checking for copy/paste errors in the tokens and ensuring that I'm not getting the tokens mixed up.
This is with Groovy 1.8.2, OSX Java 1.6.0_29, HTTPBuilder 0.5.1, gaelyk 1.1.
Any ideas? Thanks.
OK, no response on this so here's how I worked around it.
I gave up on using oauth... google only claim 'experimental' status for this anyway so maybe it fundamentally doesn't work yet.
However I get good results using the ClientLogin protocol from my test client (equivalent to doing a manual login to Google Accounts like the one you do when accessing gmail)
I based this on the extremely useful article http://www.geekyblogger.com/2011/05/using-clientlogin-to-do-authentication.html. I had to extend in a few ways, code below:
import java.io.File;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.nio.charset.Charset;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import com.google.appengine.repackaged.com.google.common.io.Files;
import com.google.cloud.sql.jdbc.internal.Charsets;
public class Login {
public static void main(String[] args) throws Exception {
// This file contains my
// google password. Note that this has to be an app-specific
// password if you use 2-step verification
File passFile = new File("/Users/me/pass.txt");
String pass = Files.toString(passFile, Charsets.UTF_8);
String authCookie = loginToGoogle("myemail#gmail.com", pass,
"http://myapp.appspot.com");
DefaultHttpClient client = new DefaultHttpClient();
// A te
HttpGet get = new HttpGet("http://myapp.appspot.com/rest/blah");
get.setHeader("Cookie", authCookie);
HttpResponse response = client.execute(get);
response.getEntity().writeTo(System.out);
}
public static String loginToGoogle(String userid, String password,
String appUrl) throws Exception {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(
"https://www.google.com/accounts/ClientLogin");
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("accountType", new StringBody("HOSTED_OR_GOOGLE",
"text/plain", Charset.forName("UTF-8")));
reqEntity.addPart("Email", new StringBody(userid));
reqEntity.addPart("Passwd", new StringBody(password));
reqEntity.addPart("service", new StringBody("ah"));
reqEntity.addPart("source", new StringBody(
"YourCompany-YourApp-YourVersion"));
post.setEntity(reqEntity);
HttpResponse response = client.execute(post);
if (response.getStatusLine().getStatusCode() == 200) {
InputStream input = response.getEntity().getContent();
String result = IOUtils.toString(input);
String authToken = getAuthToken(result);
post = new HttpPost(appUrl + "/_ah/login?auth=" + authToken);
response = client.execute(post);
Header[] cookies = response.getHeaders("SET-COOKIE");
for (Header cookie : cookies) {
if (cookie.getValue().startsWith("ACSID=")) {
return cookie.getValue();
}
}
throw new Exception("ACSID cookie cannot be found");
} else
throw new Exception("Error obtaining ACSID");
}
private static String getAuthToken(String responseText) throws Exception {
LineNumberReader reader = new LineNumberReader(new StringReader(
responseText));
String line = reader.readLine();
while (line != null) {
line = line.trim();
if (line.startsWith("Auth=")) {
return line.substring(5);
}
line = reader.readLine();
}
throw new Exception("Could not find Auth token");
}
}

Resources