Receiving 403 method not allowed from Spring Security - angularjs

I'm building an app with an AngularJS front end and Spring backend. I have everything setup for CSRF on both the front end and the backend and it was working fine until a change I made.
When I log into my app everything goes fine, I login at an endpoint I made at /rest/user. It's when I logout that the 403 error is thrown. I have Spring Security printing to a log file in debug mode and I see that it fails when it tries to validate the CSRF token. I'll go ahead and explain what I did that cause this to happen.
I'm serving the AngularJS app as static content from the Spring dispatcher servlet and I don't want Spring Security to secure that static content. I figure it's just more load on the server. So I've set the Spring Security Filter Chain entry point to be where my rest services are mapped to instead of the root of the app.
Here's the sections of my web.xml showing this:
<servlet>
<servlet-name>gravytrack</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>gravytrack</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>gravytrack</servlet-name>
<url-pattern>*.*</url-pattern>
</servlet-mapping>
<!-- Security entry point -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/rest/*</url-pattern>
</filter-mapping>
Because of this change, I've had to map my logout url to /rest/logout instead of the normal /logout that spring security maps it to by default. Here's my security configuration showing this:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<global-method-security pre-post-annotations="enabled"
secured-annotations="enabled"/>
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/rest/**" requires-channel="https"/>
<access-denied-handler error-page="/"/>
<http-basic entry-point-ref="gtBasicAuthenticationEntryPoint"/>
<!-- CRSF FILTER CONFIG -->
<custom-filter ref="csrfHeaderFilter" after="CSRF_FILTER"/>
<csrf token-repository-ref="csrfTokenRepository" />
<!-- LOGOUT CONFIG -->
<logout logout-url="/rest/logout" invalidate-session="true" delete-cookies="JSESSIONID"/>
<!--<session-management invalid-session-url="/">-->
<!--<concurrency-control max-sessions="10" error-if-maximum-exceeded="true" />-->
<!--</session-management>-->
</http>
<!--<beans:bean id="gtBasicAuthenticationEntryPoint" class="com.gbsolutions.gravytrack.security.GtBasicAuthenticationEntryPoint">-->
<!--<beans:property name="realmName" value="gravytrack" />-->
<!--</beans:bean>-->
<beans:bean id="csrfTokenRepository" class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository">
<beans:property name="headerName" value="X-XSRF-TOKEN" />
</beans:bean>
<!--<beans:bean class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" id="passwordEncoder" />-->
<authentication-manager alias="authenticationManager">
<authentication-provider>
<!--<password-encoder ref="passwordEncoder"/>-->
<!--<jdbc-user-service data-source-ref="dataSource"-->
<!--users-by-username-query="SELECT email as username, password, enabled FROM user_account-->
<!--WHERE email = ?" />-->
<user-service>
<user name="admin#admin.com" password="admin" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
I have a custom filter that you can see on this line of the security config:
<custom-filter ref="csrfHeaderFilter" after="CSRF_FILTER"/>
This is where I modify the returned cookie to take a CSRF token customized for Angular. Here's the csrfHeaderFilter class:
#Service("csrfHeaderFilter")
public class CsrfHeaderFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie==null || token!=null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
}
I believe the problem has something to do with this line:
cookie.setPath("/");
I've had a similar problem to this before and I fixed it by changing the path to the path of my app. But right now the path of my app is the root of tomcat because of how I have setup tomcat. So instead of https://localhost:8443/gravytrack it's just https://localhost:8443/.
I've also tried changing the path to /rest (the entry point of my Spring Security) and this didn't help. What could be causing this 403 error?

Related

Spring CSRF + AngularJs

I Already tried many of the aswers about this topic, no one works for me.
I Have a basic CRUD with Spring MVC 4.1.7, Spring Security 3.2.3 working on MySQL + Tomcat7.
The problem is, when i try to POST form with AngularJS, I keep being blocked by error 403 ( access denied ).
I figured out that I need to send my CSRF_TOKEN with the POST request, but I can't figure out HOW!
I Tried so many diferent ways and no one works.
My Files
Controller.js
$scope.novo = function novo() {
if($scope.id){
alert("Update - " + $scope.id);
}
else{
var Obj = {
descricao : 'Test',
saldo_inicial : 0.00,
saldo : 33.45,
aberto : false,
usuario_id : null,
ativo : true
};
$http.post(urlBase + 'caixas/adicionar', Obj).success(function(data) {
$scope.caixas = data;
}).error(function(data) {alert(data)});
}
};
Spring-security.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!-- enable use-expressions -->
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/seguro**"
access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
<intercept-url pattern="/seguro/financeiro**"
access="hasAnyRole('ROLE_FINANCEIRO','ROLE_ADMIN')" />
<!-- access denied page -->
<access-denied-handler error-page="/negado" />
<form-login login-page="/home/" default-target-url="/seguro/"
authentication-failure-url="/home?error" username-parameter="inputEmail"
password-parameter="inputPassword" />
<logout logout-success-url="/home?logout" />
<!-- enable csrf protection -->
<csrf />
</http>
<!-- Select users and user_roles from database -->
<authentication-manager>
<authentication-provider>
<password-encoder hash="md5" />
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT login, senha, ativo
FROM usuarios
WHERE login = ?"
authorities-by-username-query="SELECT u.login, r.role
FROM usuarios_roles r, usuarios u
WHERE u.id = r.usuario_id
AND u.login = ?" />
</authentication-provider>
</authentication-manager>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Barattie ~ Soluções Integradas</display-name>
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/spring-security.xml
/WEB-INF/spring/spring-database.xml
/WEB-INF/spring/spring-hibernate.xml
</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.writeStateAtFormEnd</param-name>
<param-value>false</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/home</url-pattern>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/erro</location>
</error-page>
UPDATE
I tried to add to rename at client side the xsrf, but I keep getting access denied.
var app = angular.module('myApp', []).config(function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = '_csrf';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRF-Token';
});
** UPDATE 2 **
I tried to implement a filter like this.
package sys.barattie.util;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.web.filter.OncePerRequestFilter;
public class CsrfFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = new Cookie("XSRF-TOKEN", csrf.getToken());
cookie.setPath("/");
response.addCookie(cookie);
}
filterChain.doFilter(request, response);
}
}
And changed my spring security to it.
<csrf token-repository-ref="csrfTokenRepository" />
<beans:bean id="csrfTokenRepository" class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository">
<beans:property name="headerName" value="X-XSRF-TOKEN" />
</beans:bean>
Web.xml
<filter>
<filter-name>csrfFilter</filter-name>
<filter-class>sys.barattie.util.CsrfFilter</filter-class>
</filter>
But it is like that the server doesn't run the filter, I've added a System.out.println to it, but can't see the messages in the debug
I did some tests and end up with this.
In my login controller, if my user authentication is successful, I create a token with the name of the AngularJS Token, just like this.
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = new Cookie("XSRF-TOKEN", csrf.getToken());
cookie.setPath("/");
response.addCookie(cookie);
}
After that, I can manage my $http.post successfully.
I don't know if this is the best way, but is the way that worked for me!
Thanks for the help #Joao Evangelista
The main problem is the integration, Angular always look for a cookie name XSRF-TOKEN and Spring sends a CSRF_TOKEN, you need to provide a filter to change this. Something like this:
private static Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName())
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN")
String token = csrf.getToken()
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token)
cookie.setPath("/")
response.addCookie(cookie)
}
}
filterChain.doFilter(request, response)
}
}
}
static CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository()
repository.setHeaderName("X-XSRF-TOKEN")
return repository
}
NOTICE The only example I have is this, is written in Groovy, but is just missing some ;
Then you need to add the filter and the repository to <csrf/> properties, you can explicity set a class implementing a Filter as <bean>, using #Component or declaring this methods as #Bean on a configuration class
Otherwise you can change the $http configuration on Angular, according to docs setting this settings to match Spring token cookie name and header name
xsrfHeaderName – {string} – Name of HTTP header to populate with the XSRF token.
xsrfCookieName – {string} – Name of cookie containing the XSRF token.
More info about this you can check the docs on Usage section
i was facing this problem also, and this is the solution that is working for me (from the Spring documentation), notice that im not using $http. Instead im using $resource.
'
You can ask Spring to save a cookie with Angular's defaults:
<csrf token-repository-ref="tokenRepository"/>
...
</http>
<b:bean id="tokenRepository"
class="org.springframework.security.web.csrf.CookieCsrfTokenRepository"
p:cookieHttpOnly="false"/>
Please notice that if you use $http, there is a field in the config object called xsrfCookieName, where you can set explicitly the name of the cookie. But this option i havent tried it, so i dont know how useful it is.
Best Regards.
This should work:
Class that extends WebSecurityConfigurerAdapter:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
..
And then in your AngularJS you can use any module for csrf, etc.: spring-security-csrf-token-interceptor

Uploading files with PrimeFaces 4.0 , and jsf 2.2 on google app engine

I'm using:
-primefaces 4.0
-jsf mojarra 2.2
-google app engine (servlet api 2.5)
and this solution (Getting primefaces p:fileUpload to work under google appengine) doesn't help me because my version of primefaces is higher. There is exception when I'm using my form below with p:commandButton:
java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.getPart(Ljava/lang/String;)Ljavax/servlet/http/Part;
at org.primefaces.component.fileupload.NativeFileUploadDecoder.decodeAdvanced(NativeFileUploadDecoder.java:60)
at org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:37)
at org.primefaces.component.fileupload.FileUploadRenderer.decode(FileUploadRenderer.java:44)
at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:831)
at javax.faces.component.UIInput.decode(UIInput.java:771)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1225)
at javax.faces.component.UIInput.processDecodes(UIInput.java:676)
at javax.faces.component.UIForm.processDecodes(UIForm.java:225)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:929)
at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
....
and this is because google don't support servlet api 3.0. I realy can't find a solution for now. Running primefaces 3.5 is not a option because the project is with JSF 2.2 and 2.2 is not compatible with primefaces 3.5.
One usable comment from this topic: How to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null
Update: since PrimeFaces 4.x, when used in combination with JSF 2.2 and Servlet 3.0, the filter is not necessary anymore. The Servlet 3.0 / JSF 2.2 native API will be used instead of Apache Commons FileUpload. Other rules however still apply and from the possible causes you can scratch #1 and #2.
My form:
<h:form enctype="multipart/form-data">
<p:fileUpload id="filePhoto" fileUploadListener="#{atlasCasesMB.handleFileUpload}" mode="advanced" dragDropSupport="false"
update=":messages" sizeLimit="614400" fileLimit="3" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" />
</h:form>
In this form fileUploadListener is not invoked.
I've tried to use the solution from this topic: Getting primefaces p:fileUpload to work under google appengine modify the DiskFileItem), but obviously this cannot help because JSF 2.2 uses native API instead of Apache Commons FileUpload.
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
<init-param>
<param-name>thresholdSize</param-name>
<param-value>2147483647</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
Any suggestions? (Downgrading primefaces and jsf is not an option because the project is in final stage)
The solution ,that I tried, is to force primefaces to use apache common file upload (commons-fileupload-1.3.jar) using this:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value>
</context-param>
Then I used the filter:
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
<init-param>
<param-name>thresholdSize</param-name>
<param-value>2147483647</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
important here is to set thresholdSize so big that write method in some of the apache common classes(I forgot which) is not invoked. And finally add the filter FileUploadFilter from primefaces 4.0 source files: http://www.primefaces.org/downloads.html
All sources that I used to get to this point:
http://davebarber.blog.com/2010/10/15/jsf-2-0-on-google-app-engine/
PrimeFaces 4.0 FileUpload works with Mojarra 2.2 but not MyFaces 2.2
How to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null
Getting primefaces p:fileUpload to work under google appengine
This fires :
java.lang.verifyerror inconsistent stackmap frames at branch target
To prevent primefaces to use its native file upload, add the following parameter.
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value>
</context-param>
Then I used the filter:
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
<init-param>
<param-name>thresholdSize</param-name>
<param-value>2147483647</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
important here is to set thresholdSize so big that write method in some of the apache common classes(I forgot which) is not invoked. And finally add the filter FileUploadFilter from primefaces 4.0 modified:
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);
logger.warning("init:uploadDir=" + uploadDir + "; thresholdSize=" + thresholdSize);
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
boolean isMultipart = ServletFileUpload.isMultipartContent(httpServletRequest);
if (isMultipart) {
logger.warning("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");
}
}
Form:
<h:form >
<p:fileUpload id="filePhoto" fileUploadListener="#{atlasCasesMB.handleFileUpload}" mode="advanced" dragDropSupport="false"
update=":messages" sizeLimit="614400" fileLimit="3" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" />
<br />
<p:commandButton value="#{bundle['save']}" actionListener="#{atlasCasesMB.saveCase}" process="#form" />
</h:form>
File upload handler:
public void handleFileUpload(FileUploadEvent event) {
log.warning("handleFileUpload(FileUploadEvent event)");
UploadedFile uploadedFile = event.getFile();
photosArr.add(uploadedFile.getContents());
//photos.add(new File(uploadedFile.getFileName()));
FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
List of byte array photos:
private List<byte[]> photosArr;
libraries:
commons-fileupload-1.3.jar
commons-io-2.4.jar
gmultipart-0.2.jar
portlet-2.0.jar
primefaces-4.0.jar
DiskFileItem:
comment UID and inside of write method
and ViewScoped Bean
========================================
there is second way to do this:
using multipart request to jersey:
<p:dialog id="upladPhotoDialog" widgetVar="upladPhotoDlg" header="#{bundle['uploading.photos']}" >
<form action="rest/case" method="post" enctype="multipart/form-data">
<p>#{bundle['upload.photo.select.images.to.upload']}</p>
<br />
<input id="photo1" type="file" name="photo1" />
<br />
<input id="photo2" type="file" name="photo2" />
<br />
<input id="photo3" type="file" name="photo3" />
<br />
<input id="caseId" type="text" name="caseId" style="display:none" value="#{atlasCasesMB.savedCaseId}" />
<br />
<input id="btn-post" class="active btn" type="submit" value="Send" />
</form>
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void insertPhotoForCase (
#FormDataParam("photo1") InputStream photoIS1,
#FormDataParam("photo2") InputStream photoIS2,
#FormDataParam("photo3") InputStream photoIS3,
#FormDataParam("caseId") String caseId , #Context HttpServletRequest httpRequest , #Context HttpServletResponse httpResponse) {
try {
DataService<Case> das = new CaseDataService();
Case caze = das.find(Integer.parseInt(caseId));
byte[] photoBytes = IOUtils.toByteArray(photoIS1);
if(photoBytes.length != 0 ){
sendPhotoToBlob (createPhoto(caze).getId() ,photoBytes);
}
photoBytes = IOUtils.toByteArray(photoIS2);
if(photoBytes.length != 0 ){
sendPhotoToBlob (createPhoto(caze).getId() ,photoBytes);
}
photoBytes = IOUtils.toByteArray(photoIS3);
if(photoBytes.length != 0 ){
sendPhotoToBlob (createPhoto(caze).getId() ,photoBytes);
}
//currentResponse.sendRedirect("/atlascases.xhtml");
_context.getRequestDispatcher("/atlascases.xhtml").forward(httpRequest, httpResponse);
} catch (Exception e) {
e.printStackTrace();
}
}
file:jersey-multipart-config.properties in src folder with text inside:
bufferThreshold = -1
in web.xml
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.smartinteractive.medimaging.service</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>

GAE - cannot deploy gwt app which uses UserService

I tried to deploy my app using auth this instructions as :
<application>mytestapp</application>
<version>1</version>
<sessions-enabled>true</sessions-enabled>
<security-constraint>
<web-resource-collection>
<web-resource-name></web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
and I tried this code as well to make user login:
public class GuestbookServlet extends HttpServlet {
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
if (user != null) {
resp.setContentType("text/plain");
resp.getWriter().println("Hello, " + user.getNickname());
} else {
resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));
}
}
}
... but for some reason I get exception thrown as XML error validating :
An internal error occurred during: "Deploying testapp to Google". XML
error validating C:...\testapp\war\WEB-INF\appengine-web.xml against
C:...\eclipse-jee-indigo-win32\eclipse\plugins\com.google.appengine.eclipse.sdkbundle_1.5.2.r37v201107211953\appengine-java-sdk-1.5.2\docs\appengine-web.xsd
I am not pretty sure what that means so I dearly need your advise how to fix it? Any useful idea is much appreciated.
Thanks
P.S. GWT SDK 2.3
You are mixing the app config file: appengine-web.xml with deployment descriptor: web.xml.

Jersey Google app engine - Resource not found

I am deploying a sample app in Google App Engine that uses Jersey. However when I try to do a GET or POST to the REST resource I get a - 404 NOT FOUND error. Looks like I am missing something.
REST resource code:
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.codehaus.jettison.json.JSONObject;
#Path("/stream")
public class StreamingResource {
private static final Logger log = Logger
.getLogger(FacebookStreamingResource.class.getName());
#POST
#Path("/callback")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.TEXT_PLAIN)
public String putStreamData(JSONObject jsonEntity) {
return jsonEntity.toString();
}
#GET
#Path("/get")
#Produces(MediaType.TEXT_PLAIN)
public String getStreamData() {
return "Get successful";
}
}
Here is the web.xml file
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>SystemServiceServlet</servlet-name>
<servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
<init-param>
<param-name>services</param-name>
<param-value />
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SystemServiceServlet</servlet-name>
<url-pattern>/_ah/spi/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>JerseyWebApplication</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.vbv.fb</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JerseyWebApplication</servlet-name>
<url-pattern>/stream/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
I have included the following jars:
asm-3.1.jar
jersey-client-1.12.jar
jersey-core-1.12.jar
jersey-json-1.12.jar
jersey-server-1.12.jar
jersey-servlet-1.12.jar
jettison-1.1.jar
jackson-core-asl-1.7.1.jar
jackson-jaxrs-1.7.1.jar
jackson-mapper-asl-1.7.1.jar
jackson-xc-1.7.1.jar
App Engine SDK version is 1.7.0
Any suggestions would be greatly appreciated :)
When I changed the in web.xml from /stream/* to /* it works :)

No resource classes found on a cxf Servlet

I have created a very simple cxf non-spring based Servlet which loads a javax.ws.rs.Application type.
Here is the web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>
com.mycomp.cxf.TestApplication
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
And here is the application:
public class TestApplication extends Application
{
private final Set<Class<?>> classes = new HashSet<Class<?>>();
private final Set<Object> singletons = new HashSet<Object>();
public TestApplication() throws ServletException
{
}
#Override
public Set<Class<?>> getClasses()
{
return classes;
}
#Override
public Set<Object> getSingletons()
{
return singletons;
}
}
The Servlet is failing to load due to: "No resource classes found" and i'm not sure why as it should be ok to have an empty set of classes in Application.
Here is the full stacktrace:
org.apache.cxf.jaxrs.AbstractJAXRSFactoryBean - No resource classes found
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/test] - StandardWrapper.Throwable
org.apache.cxf.service.factory.ServiceConstructionException
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:122)
at org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet.createServerFromApplication(CXFNonSpringJaxrsServlet.java:304)
at org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet.loadBus(CXFNonSpringJaxrsServlet.java:72)
at org.apache.cxf.transport.servlet.AbstractCXFServlet.init(AbstractCXFServlet.java:78)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1172)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:992)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4058)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4371)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at com.springsource.osgi.webcontainer.tomcat.TomcatServletContainer.startWebApplication(TomcatServletContainer.java:120)
at com.springsource.osgi.webcontainer.internal.StandardWebContainer$StandardWebApplication.start(StandardWebContainer.java:100)
at com.springsource.osgi.webcontainer.extender.WebContainerBundleCustomizer.addingBundle(WebContainerBundleCustomizer.java:25)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:440)
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:261)
at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:233)
at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:413)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:919)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227)
at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:149)
at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEventPrivileged(Framework.java:1349)
at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEvent(Framework.java:1300)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:380)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:284)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:276)
at com.sap.core.js.deployer.watchservice.WARDeployer.deploy(WARDeployer.java:142)
at com.sap.core.js.deployer.watchservice.FileSystemEventsListener.onChange(FileSystemEventsListener.java:26)
at com.springsource.util.io.FileSystemChecker.notifyListeners(FileSystemChecker.java:182)
at com.springsource.util.io.FileSystemChecker.check(FileSystemChecker.java:145)
at com.sap.core.js.deployer.watchservice.WatchTask.run(WatchTask.java:29)
at java.lang.Thread.run(Thread.java:679)
Caused by: javax.ws.rs.WebApplicationException
at org.apache.cxf.jaxrs.AbstractJAXRSFactoryBean.checkResources(AbstractJAXRSFactoryBean.java:238)
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:85)
... 31 more
10:41:54,580 [ERROR] org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/test] - Servlet /test threw load() exception
javax.ws.rs.WebApplicationException
at org.apache.cxf.jaxrs.AbstractJAXRSFactoryBean.checkResources(AbstractJAXRSFactoryBean.java:238)
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:85)
at org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet.createServerFromApplication(CXFNonSpringJaxrsServlet.java:304)
at org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet.loadBus(CXFNonSpringJaxrsServlet.java:72)
at org.apache.cxf.transport.servlet.AbstractCXFServlet.init(AbstractCXFServlet.java:78)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1172)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:992)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4058)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4371)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at com.springsource.osgi.webcontainer.tomcat.TomcatServletContainer.startWebApplication(TomcatServletContainer.java:120)
at com.springsource.osgi.webcontainer.internal.StandardWebContainer$StandardWebApplication.start(StandardWebContainer.java:100)
at com.springsource.osgi.webcontainer.extender.WebContainerBundleCustomizer.addingBundle(WebContainerBundleCustomizer.java:25)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:440)
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:261)
at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:233)
at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:413)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:919)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227)
at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:149)
at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEventPrivileged(Framework.java:1349)
at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEvent(Framework.java:1300)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:380)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:284)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:276)
at com.sap.core.js.deployer.watchservice.WARDeployer.deploy(WARDeployer.java:142)
at com.sap.core.js.deployer.watchservice.FileSystemEventsListener.onChange(FileSystemEventsListener.java:26)
at com.springsource.util.io.FileSystemChecker.notifyListeners(FileSystemChecker.java:182)
at com.springsource.util.io.FileSystemChecker.check(FileSystemChecker.java:145)
at com.sap.core.js.deployer.watchservice.WatchTask.run(WatchTask.java:29)
at java.lang.Thread.run(Thread.java:679)
You need to notify your environment of your serviceclasses. You first need to add the service class, otherwise you will just return null in getSingletons()
So just change your now empty constructor to add the service class:
class TestApplication extends Application {
public TestApplication() throws ServletException
{
singletons.add( new com.example.MyService() )
}
....
}
Well, I guess you can't have an empty set of classes as if I add one then it loads successfully, for example:
public TestApplication() throws ServletException
{
singletons.add(someClass);
}

Resources