GWT Upload fails to App Engine - google-app-engine

I want to provide a file upload to Google App Engine with the "GWT Upload" (https://code.google.com/p/gwtupload/). During the upload I get an error. As UploadAction servlet I use the build in: gwtupload.server.gae.AppEngineUploadAction
The servlet is configured in the web.xml in the following way:
<context-param>
<!-- max size of the upload request -->
<param-name>maxSize</param-name>
<param-value>3145728</param-value>
</context-param>
<context-param>
<!-- Useful in development mode to slow down the uploads in fast networks.
Put the number of milliseconds to sleep in each block received in the server.
false or 0, means don't use slow uploads -->
<param-name>slowUploads</param-name>
<param-value>200</param-value>
</context-param>
<servlet>
<servlet-name>uploadServlet</servlet-name>
<!-- This is the default servlet, it puts files in session -->
<servlet-class>gwtupload.server.gae.AppEngineUploadAction</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>uploadServlet</servlet-name>
<url-pattern>*.gupld</url-pattern>
</servlet-mapping>
During upload the progress bar progresses some percentages and then shows the following error:
But there are no more details in the logs.
The error message shows the class gwtupload.server.gae.MemCacheFileItemFactory$CacheableFileItem with the method setHeader(). That's strange because I can't find the method in that class. What's happening here?
Edit:
This is basically all the custom code i use. On the server side i use the build in gwtupload.server.gae.AppEngineUploadAction servlet.
package com.uploadtest.client;
import gwtupload.client.IUploadStatus.Status;
import gwtupload.client.IUploader;
import gwtupload.client.IUploader.UploadedInfo;
import gwtupload.client.MultiUploader;
import gwtupload.client.PreloadedImage;
import gwtupload.client.PreloadedImage.OnLoadPreloadedImageHandler;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.RootPanel;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class GWTUploadTest2 implements EntryPoint {
// A panel where the thumbnails of uploaded images will be shown
private FlowPanel panelImages = new FlowPanel();
public void onModuleLoad() {
// Attach the image viewer to the document
RootPanel.get("thumbnails").add(panelImages);
// Create a new uploader panel and attach it to the document
MultiUploader defaultUploader = new MultiUploader();
RootPanel.get("default").add(defaultUploader);
// Add a finish handler which will load the image once the upload finishes
defaultUploader.addOnFinishUploadHandler(onFinishUploaderHandler);
}
// Load the image in the document and in the case of success attach it to the viewer
private IUploader.OnFinishUploaderHandler onFinishUploaderHandler = new IUploader.OnFinishUploaderHandler() {
public void onFinish(IUploader uploader) {
if (uploader.getStatus() == Status.SUCCESS) {
new PreloadedImage(uploader.fileUrl(), showImage);
// The server sends useful information to the client by default
UploadedInfo info = uploader.getServerInfo();
System.out.println("File name " + info.name);
System.out.println("File content-type " + info.ctype);
System.out.println("File size " + info.size);
// You can send any customized message and parse it
System.out.println("Server message " + info.message);
}
}
};
// Attach an image to the pictures viewer
private OnLoadPreloadedImageHandler showImage = new OnLoadPreloadedImageHandler() {
public void onLoad(PreloadedImage image) {
image.setWidth("75px");
panelImages.add(image);
}
};
}
In addition to that i added the following jars to my clath path:
log4j-1.2.17.jar
gwtupload-gae-0.6.6.jar
gwtupload-0.6.6.jar
commons-fileupload-1.3.jar
commons-io-2.4.jar
Also zipped my whole sample project and uploaded it here:
https://skydrive.live.com/redir?resid=60B826E451F52B4D!118&authkey=!ALa1n2mL2sRR0wU
Edit 2:
Like Manolo pointed out: I was using "commons-fileupload-1.3.jar" instead of "commons-fileupload-1.2.1.jar". Changing the jar fixed my problem!

The problem is in the version of the commons-fileupload you are using, change it to the version 1.2.1, which is the one pointed in the gwtupload documentation.
It should work with 1.2.2 as well, but to use 1.3 requires new methods (setHeaders) which are not in the UploadListeners provided with gwtupload.
You should change in your project the target java (JDK compliance) to 1.6, since it is the last one supported in GWT to avoid problems, although it runs in 1.7.

Related

Microsoft Android application is not matching the signature hash with the application reply URI

Goal: Use the MS Identity application that was created by Microsoft and try to tailor the application according to our needs.
Issue The android application is not matching the signature hash with the Applications' Reply URI.
Configuration Values
Signature Hash: ga0RGNYHvNM5d0SLGQfpQWAPGJ8=
Redirect URI: msauth://com.azuresamples.msalandroidapp/ga0RGNYHvNM5d0SLGQfpQWAPGJ8%3D
Android:host: com.azuresamples.msalandroidapp
Android Scheme: msauth
Logs and Screenshots
Logs show: The redirect URI in the configuration file doesn't match with the one generated with package name and signature hash.
Screenshot of the error in the Android Emulator
Methods Tried
Tried to fix this by changing the android:path value to /ga0RGNYHvNM5d0SLGQfpQWAPGJ8%3D however got this message from the UI:
Screenshot of the update android:path value
Tried to change the Reply URI directly from Azure Portal, but was not able to
Tried changing the Redirect URI in the android code to msauth://com.azuresamples.msalandroidapp/ga0RGNYHvNM5d0SLGQfpQWAPGJ8%3D but that gave the same error
The default library in the code was 1.2, changed it to 1.5+ in gradle and still it didnt work.
Configuration Files
auth_config_single_account.json
"client_id" : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"authorization_user_agent" : "DEFAULT",
"redirect_uri" : "msauth://com.azuresamples.msalandroidapp/ga0RGNYHvNM5d0SLGQfpQWAPGJ8%3D",
"account_mode" : "SINGLE",
"broker_redirect_uri_registered": true,
"authorities" : [
{
"type": "AAD",
"authority_url": "https://login.microsoftonline.com/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
]
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.azuresamples.msalandroidapp">
...
<intent-filter>
...
<data
android:host="com.azuresamples.msalandroidapp"
android:path="/ga0RGNYHvNM5d0SLGQfpQWAPGJ8="
android:scheme="msauth" />
</intent-filter>
...
</manifest>
Build-Gradle:app
...
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "androidx.appcompat:appcompat:$rootProject.ext.appCompatVersion"
implementation "com.google.android.material:material:$rootProject.ext.materialVersion"
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.android.volley:volley:1.1.1'
if (findProject(':msal') != null) {
// For developer team only.
localImplementation project(':msal')
externalImplementation 'com.microsoft.identity.client:msal:1.5.+'
}
else {
// Downloads and Builds MSAL from maven central.
implementation 'com.microsoft.identity.client:msal:1.5.+'
}
}
Update
Was trying to avoid this but I have updated my keystore using the debug.keystore that microsoft provides and it works, however this is not solution for production environments. What are the steps I need to take for this to work in the production environment.
Not sure if it will be a relevant answer, but will share my experience.
At some point I run into the same issue, dig into the library and figured out how hash is calculated there. It was something like this (I have translated it into kotlin):
try {
val info = packageManager.getPackageInfo(
packageName,
PackageManager.GET_SIGNATURES
)
for (signature in info.signatures) {
val md = MessageDigest.getInstance("SHA")
md.update(signature.toByteArray())
val hash = Base64.encodeToString(
md.digest(),
Base64.DEFAULT
)
Log.d("KeyHash", "KeyHash:$hash")
}
} catch (e: PackageManager.NameNotFoundException) {
Log.d("KeyHash", e.toString())
} catch (e: NoSuchAlgorithmException) {
}
The value calculated this way didn't match the value from running this command:
keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64
But it was the one that msal library expects to get. Same happened on release signature. I haven't yet investigated the reason (maybe I did something wrong), but for now I'm using signature hash got from the first method, and it works fine.
This is Dome from the MSAL Android team.
If you want to use your own keystore, you will have to register your own application.
com.azuresamples.msalandroidapp was only registered with the signature hash of the provided debug.keystore.
Please let me know if you have any other question. You can also leave a question in our GitHub repository as well (we're constantly monitoring that one).
I tried with cmd and keytool but not get success. Please Try this code to generate key hash programmatically in you code.
String packageName = getApplicationContext().getPackageName();
try {
PackageInfo info = getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md;
md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
sha1Singature = new String(Base64.encode(md.digest(), 0));
//String something = new String(Base64.encodeBytes(md.digest()));
Log.e(AppConstants.TAG, sha1Singature);
}
} catch (PackageManager.NameNotFoundException e1) {
Log.e("name not found", e1.toString());
} catch (NoSuchAlgorithmException e) {
Log.e("no such an algorithm", e.toString());
} catch (Exception e) {
Log.e("exception", e.toString());
}
and then you set this Signature hash to Azure portal.

How to log as jsonPayload to stackdriver from google app engine using logback?

My spring boot app uses logback to log messages in json format. The app is configured to use consolelogappender (stdout).When the logs appear in stackdriver, they appear as textPayload instead of jsonPayload. Is it possible to write message to jsonPayload field in stackdriver using logback? If not, what are my options to log in json format?
Based on this Github Link it seems the issue all log entries are seen as textpayload. It has been added as a Feature Request but we do not have an ETA on when it will be available.
I'm not entirely sure if an alternative exist as Logback seems to be giving extensive log information, but if you are able to use the Stackdriver Logging Client instead, you could format the entry in order to get your object as a JsonPayLoad, although you will have specify most of the log categories yourself which can be an extra amount of work.
The easy way to do this, is to implements the transformation of TextPayload(JSON Format) to JSONPayload on the LoggingEnhacer
Check this answer How to use Stackdriver Structured Logging in App Engine Flex Java environment
It is possible via google-cloud-logging-logback library.
However, please note following (from https://cloud.google.com/logging/docs/structured-logging):
Note: message is saved as textPayload if it is the only field remaining
after the Logging agent moves the other special-purpose fields and
detect_json wasn't enabled; otherwise message remains in jsonPayload.
detect_json is not applicable to managed logging environments like
Google Kubernetes Engine.
To add more data to json add an enhancer. Example:
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.google.cloud.logging.LogEntry;
import com.google.cloud.logging.Payload;
import com.google.cloud.logging.logback.LoggingEventEnhancer;
import java.util.HashMap;
public class EventEnhancer implements LoggingEventEnhancer {
#Override
public void enhanceLogEntry(
LogEntry.Builder logEntry,
ILoggingEvent e
) {
HashMap<String, Object> map = new HashMap<>();
map.put("thread", e.getThreadName());
map.put("context", e.getLoggerContextVO().getName());
map.put("logger", e.getLoggerName());
Payload.JsonPayload payload = logEntry.build().getPayload();
map.putAll(payload.getDataAsMap());
logEntry.setPayload(
Payload.JsonPayload.of(map)
);
}
}
Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration scan="true">
<appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<log>application.log</log>
<redirectToStdout>true</redirectToStdout>
<resourceType>gae_app</resourceType>
<loggingEventEnhancer>EventEnhancer</loggingEventEnhancer>
<flushLevel>INFO</flushLevel>
</appender>
<root level="INFO">
<appender-ref ref="CLOUD"/>
</root>
</configuration>

Add Static resources in spring boot

I am a newbie to spring boot architecture. It says that to let the index pages to find static resources like js, we need to keep it under "src/main/resources/static".
Directory Structure:
Html files: src/main/webapp/WEB-INF/jsp/
js files: src/main/resources/static/js/
This is my index page:
<html ng-app="RollbackApp">
<head>
<title>My Rollback View</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.js"></script>
<script type="text/javascript" src = "js/app.js"></script>
</head>
<body>
<div ng-controller="rollbackController"><p>
<button ng-click="rollback()">RollBack</button>
</p></div>
</body>
</html>
Currently the index page is not able to load my "app.js"
My Mvc config class is as follows:
package com.manoj;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
/**
* Created by manojma on 10/13/2017.
*/
#Configuration
#EnableWebMvc
public class ApplicationWebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/static/");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".html");
return resolver;
}
}
I am unable to find the reason, why it is not able to find my js files.
Please help me with this.!!
The issue is that your resource handler isn't configured correctly. You've set /resources/static/ as your resource location. However, considering that src/main/resources is put entirely on your classpath, you should leave away the /resources part. Additionally, you should mention that you're looking on your classpath, so you should probably use classpath:/static/.
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/static/");
}
Additionally to that, you've defined the resource handler to forward requests starting from /resources/**. That means that if you relatively request js/app.js, it won't work, since it won't trigger the resource handler. You need to use resources/js/app.js:
<script type="text/javascript" src="resources/js/app.js"></script>
However, if your goal is to just statically serve some HTML pages, it's a lot easier to just put the HTML pages into the src/main/resources/static folder as well. Spring boot already serves the index.html by default as the welcome page but it can be customized.
you have to be careful of overriding any of the defaults
I struggled with connecting my static resources to my jsp pages and this is what I finally used to get it working with Spring boot 2.0. You can see my properties and also what the urls look like when mapping to static resources like images or plain html.
Next we need to define the template prefix and suffix for our JSP files in application.properties. Thus add: (the context path 'pdx' is optional and you can pick a name to match your application)
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
server.servlet.context-path=/pdx
http://localhost:8080/pdx/images/thedocks.jpg access static resources in src/main/resources/static/images/thedocks.jpg
http://localhost:8080/pdx/ loads index.html in src/main/resources/static/index.html
http://localhost:8080/pdx/css/home.css loads css class in src/main/resources/static/css/home.css
http://localhost:8080/pdx/h loads my home controller with #Controller("/") and #GetRequest(“/h”) annotations.
my jsp page loads the static image like this
<img alt="the docks" src="/pdx/images/thedocks.jpg"/>

JAX-RS webservice using #Path("/") at class level fails on TomEE+ 1.5.1

This simple root resource class fails when running on TomEE+ 1.5.1, return is a 404 error "The requested resource is not available." It is packaged as a WAR with and empty web.xml file in WEB-INF.
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
#Path("/")
#Produces({ "text/plain", "text/html", "text/xml", "application/xml", "application/json" })
public class BrokenResource {
private static final Log logger = LogFactory.getLog(BrokenResource.class);
public BrokenResource()
{
logger.info("constructed");
}
#GET
#Path("getloggedinguids")
public Response foo(#Context UriInfo uInfo)
{
return Response.ok("\n\n\nrequest URI = " + uInfo.getRequestUri()).build();
}
}
It deploys and I see these lines in the console output:
Mar 22, 2013 4:56:16 PM org.apache.openejb.server.rest.RESTService deployPojo
INFO: REST Service: http://localhost:8080/test//* -> Pojo BrokenResource
I have also tried packaging it with a web.xml that declares:
<servlet>
<servlet-name>test</servlet-name>
<display-name>Test OpenEJBRest Servlet</display-name>
<servlet-class>
org.apache.openejb.server.rest.OpenEJBRestServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Same results as with an empty web.xml file.
I also tried changing the class level #Path annotation to #Path("*") and then I get a different response, in the console output I see the following line:
WARNING: No root resource matching request path /test/getloggedinguids has been found, Relative Path: /getloggedinguids.
Finally... if I change the #Path annotation to something like #Path("/foo") then that works exactly as expected... hitting /test/foo/getloggedinguids returns the request URI..
I've be trying all sorts of variations of servlet mapping versus class level annotations and one thing is consistent... a #Path("/") annotation at the class leve always fails.
I even grabbed an example from the "RESTful Java with JAX-RS book" that uses the #Path("/") at the class level... that also fails.
Is this a bug in the CXF implementation of the JAX-RS standard? My project requires that I use a stock TomEE+ container so I can't switch to another JAX-RS implementation :-(
Instead of adding entries into the web.xml, keep in mind TomEE has native support for JAX-RS if you use the JAX-RS or TomEE+ versions.
Add a class like this and remove your web.xml entries:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/")
public class NoteTakerApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
return new HashSet<Class<?>>(Arrays.asList(BrokenResource.class, RestExceptionMapper.class, OtherClassesYouMayHave.class));
}
}

Generate and download file with jboss seam

I need to add an 'export' function to an existing web app using seam. The purpose is to export search results to a csv file. I have no problem generating a csv, but I do not know how the send the csv back to the user.
I do not want to store the csv on the server because that would be waisted storage space. How could I achieve this in jboss seam?
Use the Document Store Servlet provided by Seam.
Almost copying and pasting from the reference doc, declare the servlet in web.xml like this:
<servlet>
<servlet-name>Document Store Servlet</servlet-name>
<servlet-class>org.jboss.seam.document.DocumentStoreServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Document Store Servlet</servlet-name>
<url-pattern>/seam/docstore/*</url-pattern>
</servlet-mapping>
Then create a export.xhtml file with only <s:resource> tag:
<s:resource xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
data="#{myComponent.csvData}"
contentType="application/vnd.ms-excel"
fileName="#{myComponent.csvFileName}"/>
Generate link for downloading the file in your page with <s:download>:
<s:download src="/csv/export.xhtml">
<h:outputText value="Download CSV"/>
<f:param name="param1" value="somevalue"/>
<f:param name="param2" value="someOtherValue"/>
</s:download>
Finally, implement getCsvData() and getCsvFileName() methods in your component:
// could be byte[], File or InputStream
public InputStream getCsvData() {
// generate data to be downloaded
}
public String getCsvFileName() {
return "myfile.csv";
}
Note that <s:download> propagates conversation (unless you set propagation=none). If you propagate the conversation context probably you won't need to pass any parameter. For large data set it may be preferable to not propagate the conversation and pass parameter to select the data in a request scoped component.
There's a couple of ways:
1) Check the Seam docs for info on using Seam-Excel to programmatically generate your file and then write it out using a mime-type set for CSV - this is all detailed in the docs.
However, I could not get this to work in the latest version of Seam, as it requires a response object, which used to be available from the Seam context but now only returns null.
2) Code the CSV file you want as an Excel xhtml template (see the Seam docs and example projects) and simply render this as normal using an tag.
I do this regularly and it works well, bar the restriction that you cannot supply a filename.
HTH.

Resources