Java EE 8 MVC with Ozark and Apache Tomcat

It is always fun to try out new things, features and frameworks. This time I will try to check how far Ozark framework and Java 8 MVC went :) How easy the MVC development is in reality? What first impressions are when you need something more complex, not only @GET annotation?

If you are not familiar with Java EE 8 MVC (JSR 371) specification or Ozark or looking for a ready to run solution you may jump into Resources section :)

Yet another Web UI framework?

Well, I would say it’s more like a new UI engine, re-using and combining existing technologies. Why?

Model

For models we can simply reuse CDI beans. We will have a normal data container together with @RequestScoped annotation. I am not sure if @Named CDI bean should be representing data though. Things may be go far beyond the simple POJO if not controlled properly. I must agree it so easy to use and much more type safe than using Models class to populate data. Models class is a new MVC data wrapper class for you if you are trying to avoid using @Named CDI beans, but it is also less strict in data type control. You may treat it as a simple Map where you can put whatever you want.

View

Support of existing templating engines. The cool thing is that you can use JSP or Facelets to represent the data. The more cool thing is that you can already get autocompletion feature in your IDE without any cost (At least in Eclipse) :) Yes, autocompletion works only if CDI beans are used, but anyway. Ozark claims that it supports many more templating engines, such as #Freemarker, #Handlebars, #Jade, #Mustache, #Thymeleaf or #Velocity. I did not try them, but early performance results may be found in GIT repository (https://github.com/lefloh/ozark-viewengine-loadtests)

Controller

MVC 1.0 uses JAX-RS annotations for controllers. You define JAX-RS methods within your resource class. In addition to default JAX-RS annotations there is a need to add @Controller annotation as well. The only difference is in method return type. You have to:

  • return String with view name or
  • expose view template name is via annotation @View and have a method return type as void or
  • build and return a normal Response object with custom properties.

So at the end of the day there is a new framework, aggregating CDI, JAX-RS and JSP/Facelets into one, hopefully, nice built JAX-RS based web framework. Maybe you will like it if you were looking for something like this:) Unless you are already using Spring MVC.

File upload

So, going into details - file upload form. If you are using JAX-RS to upload file then there is nothing new. Otherwise there are some steps to execute in order safely use file upload form.

Maven dependency

Add Jersey support to handle multipart forms.

<dependency>
	<groupId>org.glassfish.jersey.media</groupId>
	<artifactId>jersey-media-multipart</artifactId>
	<version>${2.x latest version}</version>
</dependency>

Configure the application

Add multipart feature to the application resources list.

@ApplicationPath("/blog")
public class BlogApplication extends javax.ws.rs.core.Application {
	@Override
	public Set<Class> getClasses() {
		final Set> resources = new HashSet<Class<?>>();

		//...

		// Add additional features such as support for Multipart.
		resources.add(MultiPartFeature.class);

		return resources;
	}
}

Implement controller method

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/upload/")
public String upload(@BeanParam FileUploadEntryRequest form) {
	Preconditions.checkArgument(form != null, "Request is missing");
	byte[] datainput = null;
	try {
		datainput = org.apache.commons.io.IOUtils.toByteArray(form.getUploadedInputStream());
	} catch (IOException e) {
		LOGGER.error("Could not retrieve image from file upload form.", e);
	}
	...

	return "redirect:/posts/";
}

When developing @BeanParam class (Full source code you can find in Github repository) you have to remember to use org.glassfish.jersey.media.multipart.FormDataParam annotations for ALL params, not only for file related properties. Default @FormParam will not be understood by Ozark (or Jersey, or both?). I would expect default JAX-RS annotation to be working as well. But what a surprise :)

Image display

Image retrieval is even easier. Just create a separate resource to get StreamingOutput by id and you should be fine!

@Path("/resources/")
public class ImageResource {

	@Inject
	private BlogEntryDao blogEntryDao;

	@GET
	@Path("/image/{img}.img")
	@Produces({ "image/*" })
	public StreamingOutput getImage(@PathParam("img") String imagePath) {
		Preconditions.checkArgument(!Strings.isNullOrEmpty(imagePath), 
			"Blog post path is empty. Image cannot be retrieved.");
		byte[] img = blogEntryDao.getImage(imagePath);

		return new StreamingOutput() {
			@Override
			public void write(OutputStream output) throws IOException, WebApplicationException {
				output.write(img);
				output.flush();
			}

		};
	}
}

And usage in the html:

<img src="/s01e07/blog/resources/image/${blogEntryBean.blogEntry.path}.img" class="img-responsive" />

Things did not tried yet

So far I did not try exception handling, event notification, form field validation and error display on form submit and many more things :)

Conclusion

First impression is really good. You have to find some things yourself if you were not using REST to develop web applications. But then you may get control over what you do and how you do. Such framework is also useful for scaling stateless web applications in more standard way without forcing to use Spring MVC or other hybrid solution.

You may argue that writing Primefaces based application is faster because there are already components ready for use.

Some things were not working in Ozark:

  • ${mvc.contextPath}. I was not able to get context path in JSP template when deploying web application other than ROOT.
  • Mounting REST path of the application to ROOT (@ApplicationPath("/")) did not work.
  • Deploying the application to Wildfly application server - no luck. Ozark seems to be tightly coupled with Jersey :) And I had no time to replace RESTEasy with Jersey in Wildfly.

Hopefully you enjoyed the reading. Have a nice day and see you next time!

Resources

Photographs by James Royal-Lawson.

vytas

Senior software engineer, software architect for java enterprise based solutions