I deployed recently a Roo/Gwt project on Google App Engine.
I spent a couple of hours but couldn't find a tutorial that shows, step by step, how can we add n authentification system (withe the Federated Login Api).
I found this very good article that provides some helpful code :
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
#SuppressWarnings("serial")
public class OpenIdDemoServlet extends HttpServlet {
private static final Map<String, String> openIdProviders;
static {
openIdProviders = new HashMap<String, String>();
openIdProviders.put("Google", "google.com/accounts/o8/id");
openIdProviders.put("Yahoo", "yahoo.com");
openIdProviders.put("MySpace", "myspace.com");
openIdProviders.put("AOL", "aol.com");
openIdProviders.put("MyOpenId.com", "myopenid.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("[<a href=\""
+ userService.createLogoutURL(req.getRequestURI())
+ "\">sign out</a>]");
} else {
out.println("Hello world! 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 + "] ");
}
}
}
}
How can I setup this authentification module? Where should I put this code because there is no "main.java" file?
Thank you very much,
Regards
This is in progress to be implemented for GWT 2.1/Roo 1.1.0. See this for more details https://jira.springsource.org/browse/ROO-1003
If you can't wait, check the Spring Security in Google App Engine article, at http://blog.springsource.com/2010/08/02/spring-security-in-google-app-engine/
That approach is not supported by Roo though (so once you change the generated code, it will be harder, but still possible, to continue using Roo)
Related
as I m new for the Calendar API so i came up with the authorization part but not able to insert events into the calendar.
While inserting events it is showing the the error
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Insufficient Permission",
"reason" : "insufficientPermissions"
} ],
"message" : "Insufficient Permission"
}
Here is my entire code, if it will help:
package com.drive;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
//import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.api.client.auth.oauth2.AuthorizationCodeFlow;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.appengine.auth.oauth2.AbstractAppEngineAuthorizationCodeServlet;
import com.google.api.client.googleapis.services.AbstractGoogleClientRequest;
import com.google.api.client.util.ArrayMap;
import com.google.api.client.util.DateTime;
import com.google.api.client.util.GenericData;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import com.google.api.services.calendar.*;
import com.google.api.services.calendar.Calendar.CalendarList;
import com.google.api.services.calendar.Calendar.Events;
import com.google.api.services.calendar.model.Acl;
import com.google.api.services.calendar.model.AclRule;
import com.google.api.services.calendar.model.CalendarListEntry;
import com.google.api.services.calendar.model.Event;
import com.google.api.services.calendar.model.EventAttendee;
import com.google.api.services.calendar.model.EventDateTime;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;
/**
* Entry sevlet for the Plus App Engine Sample. Demonstrates how to make an authenticated API call
* using OAuth2 helper classes.
*
* #author Nick Miceli
*/
public class DriveSampleServlet extends AbstractAppEngineAuthorizationCodeServlet {
// List the scopes your app requires. These must match the scopes
// registered in the Admin console for your Google Apps domain.
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
User user =UserServiceFactory.getUserService().getCurrentUser();
if(user!=null){
AuthorizationCodeFlow authFlow = initializeFlow();
Credential credential = authFlow.loadCredential(getUserId(req));
Calendar calendar =new Calendar.Builder(Utils.HTTP_TRANSPORT,Utils.JSON_FACTORY, credential).setApplicationName("ashishwaiting96").build();
// Drive drive = new Drive.Builder(Utils.HTTP_TRANSPORT, Utils.JSON_FACTORY, credential).setApplicationName("ashishwaiting96").build();
/* resp.getWriter().print("success"+calendar.acl().list(" sial.com_li54bsfij3i31a9a8uqdvurr3c#group.calendar.google.com").execute());
*/
com.google.api.services.calendar.model.Calendar calendar1 = calendar.calendars().get("primary").execute();
resp.getWriter().print("success"+calendar1.getSummary()+" "+calendar1.getKind()+" "+calendar1.getDescription());
Event event = new Event();
event.setSummary("appointment");
Date startDate = new Date();
Date endDate = new Date(startDate.getTime() + 3600000);
DateTime start = new DateTime(startDate, TimeZone.getTimeZone("UTC"));
event.setStart(new EventDateTime().setDateTime(start));
DateTime end = new DateTime(endDate, TimeZone.getTimeZone("UTC"));
event.setEnd(new EventDateTime().setDateTime(end));
Event createdEvent = calendar.events().insert("primary", event).execute();
System.out.println(createdEvent.getId());
}
}
#Override
protected AuthorizationCodeFlow initializeFlow() throws ServletException, IOException {
return Utils.initializeFlow();
}
#Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
return Utils.getRedirectUri(req);
}
}
snippet 2:
package com.drive;
import com.google.api.client.extensions.appengine.datastore.AppEngineDataStoreFactory;
import com.google.api.client.extensions.appengine.http.UrlFetchTransport;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.Preconditions;
import com.google.api.client.util.store.DataStoreFactory;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.drive.DriveScopes;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
class Utils {
private static final AppEngineDataStoreFactory DATA_STORE_FACTORY =
AppEngineDataStoreFactory.getDefaultInstance();
private static GoogleClientSecrets clientSecrets = null;
// private static Set<String> SCOPES = Collections.singleton(PlusScopes.PLUS_ME);
private static List<String> SCOPES = new ArrayList<String>();
static final String MAIN_SERVLET_PATH = "/DriveSampleServlet";
static final String AUTH_CALLBACK_SERVLET_PATH = "/oauth2callback";
static final UrlFetchTransport HTTP_TRANSPORT = new UrlFetchTransport();
static final JacksonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static GoogleClientSecrets getClientSecrets() throws IOException {
if (clientSecrets == null) {
clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
new InputStreamReader(Utils.class.getResourceAsStream("/client_secret.json")));
Preconditions.checkArgument(!clientSecrets.getDetails().getClientId().startsWith("Enter")
&& !clientSecrets.getDetails().getClientSecret().startsWith("Enter "),
"Download client_secrets.json file from https://code.google.com/apis/console/?api=plus "
+ "into plus-appengine-sample/src/main/resources/client_secrets.json");
}
return clientSecrets;
}
static GoogleAuthorizationCodeFlow initializeFlow() throws IOException {
//SCOPES.add(DriveScopes.DRIVE);
SCOPES.add(CalendarScopes.CALENDAR);
// SCOPES.add(PlusDomainsScopes.PLUS_ME);
// SCOPES.add(PlusDomainsScopes.PLUS_PROFILES_READ);
GoogleAuthorizationCodeFlow gf=
new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, getClientSecrets(), SCOPES).setDataStoreFactory(
DATA_STORE_FACTORY).setAccessType("offline").setApprovalPrompt("force").build();
return gf;
}
static String getRedirectUri(HttpServletRequest req) {
GenericUrl requestUrl = new GenericUrl(req.getRequestURL().toString());
requestUrl.setRawPath(AUTH_CALLBACK_SERVLET_PATH);
return requestUrl.build();
}
}
I added the secret.json file which is working,
any help..
Insufficient Permission error is thrown when the authenticated user does not have sufficient permissions to execute this request. When I looked at the code, I see the line
// private static Set SCOPES = Collections.singleton(PlusScopes.PLUS_ME);
is commented out. When you are trying to add the calendar events, there should be scopes with WRITE authorization to the users profile in the code. You can try uncommenting the above line or uncomment the below lines:
// SCOPES.add(PlusDomainsScopes.PLUS_ME);
// SCOPES.add(PlusDomainsScopes.PLUS_PROFILES_READ);
Here are the links that will help you:
link1
link2
Also, if you are trying to add event into some one's calendar then you should have permission to do that. Please check this scenario too.
I was trying to interate User Service to my App to restrict access. The app worked fine while in eclipse but once I deployed it to app engine it does not redirect to Google Login page as expected but comes with Error:
Server Error
The server encountered an error and could not complete your request.
Please try again in 30 seconds.
This is a section of the servlet used:
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
public class MyLogin extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
UserService userService = UserServiceFactory.getUserService();
String thisURL = "/home.html";
resp.setContentType("text/html");
if (req.getUserPrincipal() != null) {
resp.getWriter().println("<p>Hello, " +
req.getUserPrincipal().getName() +
"! You can <a href=\"" +
userService.createLogoutURL(thisURL) +
"\">sign out</a>.</p>");
} else {
resp.getWriter().println("<p>Please <a href=\"" +
userService.createLoginURL(thisURL) +
"\">sign in</a>.</p>");
}
}
}
I was able to solve this problem by moving the files I intend to protect out of the root directory.
I am implementing a SOAP web service in GAE. Since GAE does not support JAX-WS I have chosen to go this way, which is basically building the soap requests and responses myself from a servlet.
Everything works fine but how can I achieve to return the wsdl description in http://myurl/MyService?wsdl ?
I guess I must implement the GET method of my servlet but how?
I have enclosed a working implementation. Note that it's based on Servlet 3.0 spec. If you are using 2.5, the annotations wont work.
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(name="MyWSServlet", urlPatterns={"/MyService"})
public class MyWSServlet extends HttpServlet {
private static final long serialVersionUID = 3605874163075522777L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
boolean requestForWSDL = false;
Enumeration<String> params = req.getParameterNames();
while (params.hasMoreElements()) {
if ("wsdl".equalsIgnoreCase(params.nextElement())) {
requestForWSDL = true;
}
}
if (requestForWSDL) {
FileInputStream wsdlInputStream = new FileInputStream(req.getServletContext().getRealPath("/wsdl/TemperatureService.wsdl"));
byte[] buffer = new byte[1024];
resp.setContentType("application/xml");
int bytesRead = 0;
while ((bytesRead = wsdlInputStream.read(buffer)) != -1) {
resp.getOutputStream().write(buffer, 0, bytesRead);
}
wsdlInputStream.close();
resp.getOutputStream().flush();
}
}
}
I am new to google cloud storage api, as well as using servers. I'm trying to write a web application in Java using Eclipse's IDE to read in a file that is stored in google's cloud storage. I have the code to read in the file on the server side, and am not sure how to modify the sample code on the client side so that it supports an httpServlet instead of a RemoteServiceServlet. Any help or suggestions would be greatly appreciated!
Below is my code on the server side.
package com.google.gwt.sample.interfacecloud.server;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.channels.Channels;
import java.util.ArrayList;
import javax.servlet.http.*;
import com.google.gwt.sample.interfacecloud.client.GreetingService;
import com.google.appengine.api.files.AppEngineFile;
import com.google.appengine.api.files.FileReadChannel;
import com.google.appengine.api.files.FileService;
import com.google.appengine.api.files.FileServiceFactory;
import com.google.appengine.api.files.FileWriteChannel;
import com.google.appengine.api.files.GSFileOptions.GSFileOptionsBuilder;
#SuppressWarnings("serial")
public class CloudInteraction extends HttpServlet implements GreetingService{
public static final String BUCKETNAME = "obd_data";
public static final String FILENAME = "data.txt";
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
resp.setContentType("text/plain");
String filename = "/gs/" + BUCKETNAME + "/" + FILENAME;
FileService fileService = FileServiceFactory.getFileService();
AppEngineFile readableFile = new AppEngineFile(filename);
FileReadChannel readChannel =
fileService.openReadChannel(readableFile, false);
BufferedReader reader =
new BufferedReader(Channels.newReader(readChannel, "UTF8"));
String line = reader.readLine();
resp.getWriter().println("READ:"+line);
System.out.println(line);
readChannel.close();
}
#Override
public String greetServer(String name) throws IllegalArgumentException {
// TODO Auto-generated method stub
return null;
}
}
You are mixing and matching RPC with plain Servlets. You should not be doing that. Do away with RPC interfaces for such interactions if you intend to you plain Servlets. You would be better served with RequestBuilder in this scenario. Note - it is not very clear what your are requirements are?
I'm trying to have a file upload element in my JSF over Google App Engine.
I have browsed the web for several alternatives but none seem to work with GAE.
I was able to do so using JSP and servlet with BlobstoreService but couldn't find a way to make it working with JSF.
As a workaround I was trying to see if there is a way to include a JSP within a JSF but I guess this isn't doable as well.
Would be thankful to get a working example.
Thanks!
First get library http://code.google.com/p/gmultipart/ and add to your project.
And than override class org.primefaces.webapp.filter.FileUploadFilter (just put in your src).
There is code of class org.primefaces.webapp.filter.FileUploadFilter:
package org.primefaces.webapp.filter;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.gmr.web.multipart.GFileItemFactory;
import org.primefaces.webapp.MultipartRequest;
public class FileUploadFilter implements Filter {
private final static Logger logger = Logger.getLogger(FileUploadFilter.class.getName());
private final static String THRESHOLD_SIZE_PARAM = "thresholdSize";
private final static String UPLOAD_DIRECTORY_PARAM = "uploadDirectory";
private String thresholdSize;
private String uploadDir;
public void init(FilterConfig filterConfig) throws ServletException {
thresholdSize = filterConfig.getInitParameter(THRESHOLD_SIZE_PARAM);
uploadDir = filterConfig.getInitParameter(UPLOAD_DIRECTORY_PARAM);
if(logger.isLoggable(Level.FINE))
logger.fine("FileUploadFilter initiated successfully");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
boolean isMultipart = ServletFileUpload.isMultipartContent(httpServletRequest);
if(isMultipart) {
if(logger.isLoggable(Level.FINE))
logger.fine("Parsing file upload request");
//start change
FileItemFactory diskFileItemFactory = new GFileItemFactory();
/* if(thresholdSize != null) {
diskFileItemFactory.setSizeThreshold(Integer.valueOf(thresholdSize));
}
if(uploadDir != null) {
diskFileItemFactory.setRepository(new File(uploadDir));
}*/
//end change
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
MultipartRequest multipartRequest = new MultipartRequest(httpServletRequest, servletFileUpload);
if(logger.isLoggable(Level.FINE))
logger.fine("File upload request parsed succesfully, continuing with filter chain with a wrapped multipart request");
filterChain.doFilter(multipartRequest, response);
} else {
filterChain.doFilter(request, response);
}
}
public void destroy() {
if(logger.isLoggable(Level.FINE))
logger.fine("Destroying FileUploadFilter");
}
}
In managed bean write method like:
public void handleFileUpload(FileUploadEvent event) {
UploadedFile uploadedFile = event.getFile();
try {
String blobKey = BlobUtils.uploadImageToBlobStore(uploadedFile.getContentType(), uploadedFile.getFileName(), uploadedFile.getContents());
this.iconKey = blobKey;
} catch (IOException e) {
log.log(Level.SEVERE, "Ошибка при попытке загрузить файл в blob-хранилище", e);
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Ошибка при попытке загрузить файл", event.getFile().getFileName() + " не загружен!");
FacesContext.getCurrentInstance().addMessage(null, msg);
return;
}
FacesMessage msg = new FacesMessage("Успешно.", event.getFile().getFileName() + " загружен.");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
And that all.
First of all , I think that whatever you are doing with JSP should eventually work with JSF as well..
BUT,
If you are looking for a file upload component for JSF , that works on GAE ,
take a look at the PrimeFaces FileUpload
Here is another link that got an explanation on what to do in order it to work on GAE :Primefaces File Upload Filter
(haven't tried it myself...)