Multipart Configuration for JBoss Enterprise Application Platform/Application Server

Spring REST controller on Spring Boot (1.12) was not accepting multi-part requests for file upload on JBoss EAP/AS but working on Embedded Tomcat.

org.springframework.web.bind.MissingServletRequestParameterException: Required MultipartFile parameter 'file' is not present

I needed to add a multipart filter on my web xml configuration in Java

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableJpaRepositories
@EnableSpringDataWebSupport
public class Application extends SpringBootServletInitializer {

 @Override
 protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
 return application.sources(Application.class);
 }

 @Override
 public void onStartup(ServletContext servletContext) throws ServletException {
 WebApplicationContext context = createRootApplicationContext(servletContext);
 ServletRegistration.Dynamic servletRegistration = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
 servletRegistration.setLoadOnStartup(1);
 servletRegistration.addMapping("/*"); // required JBOSS EAP
 servletRegistration.setMultipartConfig(getMultiPartConfig()); // fixes multipart requests
 super.onStartup(servletContext);
 }

 private MultipartConfigElement getMultiPartConfig() {
 String location = "";
 long maxFileSize = -1;
 long maxRequestSize = -1;
 int fileSizeThreshold = 0;
 return new MultipartConfigElement(
 location,
 maxFileSize,
 maxRequestSize,
 fileSizeThreshold
 );
 }

 public static void main(String[] args) {
 SpringApplication.run(Application.class, args);
 }
}

My Spring and web.xml is configured via Java annotations.

I found this post for this configuration: http://stackoverflow.com/questions/19293862/how-make-the-setmultipartconfig-work-for-a-dynamic-added-servlet

Advertisements

CAS 3.3.1 to CAS 4.0.0 Upgrade/Migration

CAS 4.0.0 is in the process of being released, and the documentation is not comprehensive. Here are somethings I did to get from CAS 3.3.1 to CAS 4.0.0 in terms of the maven overlay project.  This was mainly to get the fix for CAS-1318.

Overlay pom dependencies

updated cas-server-webapp from 3.3.1 to 4.0.0
added cas-management-webapp 4.0.0
added cas-server-support-generic 4.0.0
added cas-server-support-x509 4.0.0
added cas-server-support-openid 4.0.0
cas-server-support-ldap 4.0.0
removed outdated dependencies from overlay/lib

Files copied over from github https://github.com/Jasig/cas/tree/master/cas-server-webapp

src/main/webapp/WEB-INF/webflow/login/login-webflow.xml
src/main/webapp/WEB-INF/webflow/logout/login-webflow.xml
src/main/webapp/WEB-INF/cas-servlet.xml (too many changes, added my changes after copying over)

Updated files

login-webflow.xml,
uncommented startAuthenticate, changed flow in serviceAuthorizationCheck to transition to startAuthenticate instead.  Note: my project was using x509check, so the commented out code seemed to run the x509check

deployerConfigContext.xml,
added namespace util
modified auditTrailManager bean to point to new class
added healthCheckMonitor bean
added registeredServiceList, modified to fit our services
added monitorsList

xml schema upgrades in overlayed xml files
beans 2 -> beans 3
webflow 1 -> webflow 2

Changed Credentials.class references to Credential.class in custom code in extensions

Relevant Links
http://jasig.github.io/cas/4.0.0/index.html
https://wiki.jasig.org/display/CASUM/Auditing+and+Statistics+Via+Inspektr
https://github.com/UniconLabs/simple-cas-overlay-template
https://github.com/Jasig/cas/blob/master/cas-server-core
https://wiki.jasig.org/display/CASUM/Best+Practice+-+Setting+Up+CAS+Locally+using+the+Maven+WAR+Overlay+Method
https://github.com/leleuj/cas-overlay-demo/blob/master/cas-overlay-server-demo/src/main/webapp/WEB-INF/deployerConfigContext.xml
https://wiki.jasig.org/display/CASUM/Upgrading
https://wiki.jasig.org/display/CASUM/X.509+Certificates
https://github.com/Jasig/cas/blob/master/cas-server-support-x509/src/test/resources/deployerConfigContext.xml
https://github.com/Jasig/cas/blob/master/cas-server-support-x509/src/main/java/org/jasig/cas/adaptors/x509/authentication/handler/support/X509CredentialsAuthenticationHandler.java
http://comments.gmane.org/gmane.comp.java.jasig.cas.user/17466
https://groups.google.com/forum/#!msg/jasig-cas-user/jS2GjedsMd4/o-MGC_Tpn7IJ
https://wiki.jasig.org/display/CASUM/OpenID
https://github.com/leleuj/cas-openid-demo/blob/master/cas-openid-server-demo/src/main/webapp/WEB-INF/cas-servlet.xml
https://groups.google.com/forum/#!msg/jasig-cas-user/jS2GjedsMd4/o-MGC_Tpn7IJ
https://wiki.jasig.org/display/CASUM/Services+Management
http://mmmsoftware.blogspot.com/2008/11/migrating-from-spring-webflow-1-to.html
http://www.jasig.org/upgrading-spring-web-flow-2-cas4
https://github.com/Jasig/cas/wiki/Installation-Guide
https://github.com/Jasig/cas/wiki/CAS4-Documentation-(GitHub-Pages)
https://github.com/Jasig/cas/blob/master/cas-server-webapp/src/main/webapp/WEB-INF/cas-servlet.xml

Each project is different, but I basically just fixed compilation errors and went through the runtime errors.  I didn’t write down the details of each change, but the relevant links should have more information on what the exact changes were.

Good luck!

RESTful Web Services Popular Standards

My two favorite resources for REST standards.  I think they cover most use cases, and their suggestions are thought out and used in practice.  I recommend that both backend and frontend developers read/watch both!

  1. Storm Path
  2. Vinay Sahni

To see other links that I liked, check out my scoop.it page.

Apache Avro JSON Decoder for List/Array of Avro Objects

I couldn’t find a good example of decoding a JSON string that’s a list/array of Avro objects on the web. I just wanted to write a post to say that it works.

Here’s a few high level things that I remember

  • Create a JSON Decoder with Schema.createArray({avroObject}.getSchema())
  • When initializing the data reader, use List<{avroObject}> and also pass in an initialized instance of List<{avroObject}> along with the JSON Decoder created above.

It should work, but I had to use the debugger a few times to clear out some JSON issues.  I hope this helps – I spent a lot of unnecessary time checking whether something like this would work.  It looks like it’s supported out of the box.

Java Generics JSON Unmarshalling Using Jackson via Jersey Resource

Jackson seems to unmarshal properly for objects with a specific class type.  For types with generics, for example List<Element>, I could only specify the List.class, and the Element JSON was unmarshalled as LinkedHashMaps instead of the Element.class.

I found a way to work around it and applied it to the Jersey use case for my unit test.

ObjectMapper mapper = new ObjectMapper();
JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, Element.class);

String json = client().resource("/some/collection").get(String.class);
List<Element> elements = mapper.readValue(json, type);

Custom Headers on Preflight Request for HTTP Method OPTIONS

I spent a few hours on this, it looks like we can’t add custom headers on a preflight request.  We’re using JQuery/Backbone/Marionette, and some of the cross origin requests (HTTP POST and GET with custom headers) are causing a preflight request to happen.

Apparently the preflight requests are generated by the browser, and we can’t control the headers in that request.  The server needs to handle the HTTP OPTIONS request properly and return a 200 code in order for the request to continue.

In my case, the OPTIONS request was going to a resource requiring authentication, so I’m thinking that I need to allow OPTIONS requests to get a response without authentication.

Here’s the helpful resource that I ran across.  http://www.sencha.com/forum/showthread.php?265119-Authorization-header-not-sent-on-preflight-OPTIONS-request

Sample Dropwizard Resource Test

I’m prototyping a dropwizard app, and it wasn’t clear in the docs how to write resource tests that handle authentication.  This example uses OAuth authentication.  I also found it annoying that there were no import statements in the documents.  Anyway, I hope this helps.  There are probably more efficient ways to do this, so I’ll update this post as I find out more.


package com.yourcompany.resource;

import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.LinkedList;
import java.util.List;

import javax.ws.rs.core.MediaType;

import org.eclipse.jetty.server.Authentication.User;
import org.junit.Before;
import org.junit.Test;

import com.yourcompany.dao.SampleDao;
import com.yourcompany.dto.SampleItem;
import com.yourcompany.dto.Sample;
import com.yourcompany.oauth.OAuthAuthenticator;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;
import com.yammer.dropwizard.auth.oauth.OAuthProvider;
import com.yammer.dropwizard.testing.ResourceTest;

public class SampleResourceTest extends ResourceTest {
 private final Sample sample = new Sample();
 private final SampleDao dao = mock(SampleDao.class);

@Override
 protected void setUpResources() {
 List<SampleItem> sampleItems = new LinkedList<SampleItem>();

 sample.setSampleItems(sampleItems);

 when(dao.fetchSample(anyString())).thenReturn(sample);
 when(dao.postSample((Sample)anyObject())).thenReturn(sample);
 addResource(new SampleResource(dao));
 addProvider(new OAuthProvider<User>(new OAuthAuthenticator(), "CLIENT_SECRET"));
 }

 @Before
 public void testBefore() {
 client().addFilter(new ClientFilter() {
 private List<Object> authorizations;

@Override
 public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
 if (authorizations == null) {
 authorizations = new LinkedList<Object>();
 authorizations.add("Bearer {test token}");
 }
 request.getHeaders().put("Authorization", authorizations);
 ClientResponse response = getNext().handle(request);

 return response;
 }
 });
 }

 @Test
 public void testFetchSample() throws Exception {
 Sample retrievedSample = client().resource(String.format("/sample-service/sample/id/", "id")).get(Sample.class);
 compareSample(retrievedSample);
 verify(dao).fetchSample(anyString());
 }

 @Test
 public void testPostSample() throws Exception {
 Sample retrievedSample = client().resource("/sample-service/sample").type(MediaType.APPLICATION_JSON_TYPE).post(Favorites.class, favorites);
 compareSample(retrievedSample);
 verify(dao).postSample((Sample)anyObject());
 }

 private void compareSample(Sample retrievedSample) {
 assertThat(retrievedSample.getWhatever()).isEqualTo(sample.getWhatever());
 // other assertions
 }
}

** EDIT
I created a TestOAuthAuthenticator that I pass into my test as a provider. This authenticator has pre-defined tokens and users for tests.