Namely the new collection api, which allows to work with collections in a more functional style, and default methods in the interfaces.
This article is a brief review of my experience of Java 8, Spring MVC, Hibernate and SSP integration.
Foreword
I've always admired the Scala language. First of all, because of the binding with external libraries (Hibernate, Spring, Spring MVC), which I still have a weakness for.
I tried to use them in Scala projects, but it seemed as if I was arranging workarounds all the time and still couldn’t write in Scala style. As if I was writing in Java, but with Scala syntax and vice versa.
That’s why I decided to follow a bit “smooth” path and use a familiar stack.
I decided to use SSP (Scala Server Pages) instead of JSP (Java Server Pages), in order to get static support on the View side and to not worry about breaking at refactoring, while you learn about it after deployment only (when some block stops being displayed or even worse, damages some data in the database)
Beginning
So, let’s start.
We’re going to use my favorite Maven.
Let’s drop Maven a hint that the project will use Java 8:
...
...
org.apache.maven.plugins
maven-compiler-plugin
compile
compile
<_source>1.8
1.8
...
...
Add necessary relations to Spring (generated by 8th Java the 4th version, which supports changes of the new JDK. It also provides a library which can operate with the byte code)/Hibernate and SSP. You may add other things to your liking. The versions are located at the «dependency management» section at the parent pom.
...
org.springframework
spring-context
org.springframework
spring-context-support
org.springframework
spring-orm
org.springframework
spring-webmvc
org.hibernate
hibernate-core
org.hibernate
hibernate-entitymanager
org.hibernate.javax.persistence
hibernate-jpa-2.0-api
org.fusesource.scalate
scalate-core_2.10
org.fusesource.scalate
scalate-spring-mvc_2.10
...
The first problem I faced was incompatibility of Scala compiler which depends on Scalate library (owing to it we have SSP support) with Java 8 byte code.
I had to write the dependency to the project at the Scala compiler, so that everything would operate.
org.scala-lang
scala-compiler
2.10.4
At first I wanted to upgrade the dependency up to 2.11, but the content changed a lot and in the latest 1.6.1 Scalate version it’s not supported yet.
We also want our SSP to be recompiled so that we could find out about the problem during compilation, not at production.
So we added the following plug-in:
...
org.fusesource.scalate
maven-scalate-plugin_2.10
1.6.1
org.scala-lang
scala-compiler
2.10.4
precompile
...
As you can notice, the same hack with Scala compiler has been added.
Some Code
I’m almost done with configuration
Now we can fool around with the code and be happy about JDK 8 facilities:
My basic DAO:
public interface BaseDAO, ID extends Serializable> extends EntityManagerAware {
Class getEntityClass();
default void persist(T entity) {
if (entity.isNew()) {
entity.assignId();
}
getEntityManager().persist(entity);
getEntityManager().flush();
}
default T find(ID id) {
return getEntityManager().find(getEntityClass(), id);
}
default void delete(T entity) {
getEntityManager().remove(entity);
}
default List findByQuery(String jpqlQueryString) {
return findByQueryWithParams(jpqlQueryString, Collections.emptyMap());
}
default List findByQueryWithParams(String jpqlQueryString, Map params) {
TypedQuery query = getEntityManager().createQuery(jpqlQueryString, getEntityClass());
for (Map.Entry entry : params.entrySet()) {
query.setParameter(entry.getKey(), entry.getValue());
}
return query.getResultList();
}
}
Unfortunately, I couldn’t go without an additional layer (an abstract class):
public abstract class AbstractBaseDAO, ID extends Serializable> implements BaseDAO {
@PersistenceContext
EntityManager entityManager;
@Override
public EntityManager getEntityManager() {
return entityManager;
}
}
DAO interface:
public interface PersonDAO extends BaseDAO {
@Override
default Class getEntityClass() {
return Person.class;
}
List findAll();
}
And implementation, accordingly:
@Repository
public class PersonDAOImpl extends AbstractBaseDAO implements PersonDAO {
@Override
public List findAll() {
return findByQuery("select p from Person p");
}
}
As a result, we have a CRUD fora repository and I think we are clearing the implementation from additional noise.
Of course, I could have used Spring Data JPA and I wouldn’t have to manually write CRUD at all, but I don’t like certain aspects of it. In a case of manually generated/assigned ID it will always execute merge instead of persist. Plus the system behavior is easier to control this way.
We also get rid of the need to use exterior libraries of Guava, which allows to write in a more functional style:
List all = personService.findAll().stream().map(PersonForm::from).collect(Collectors.toList());
View for the list display:
<%@ val people: java.util.List[name.dargiri.web.controller.PeopleController.PersonForm]%>
People
#
Username
Action
<% for(person <- people ) { %>
<%=person.id%>
<%=person.username%>
">Edit |
">Delete
<% } %>
The project build is quite simple. If you have downloaded my project and want to deploy it to the servlet container, e.g. Tomcat, then run:
mvn -P=build clean package
And can see how SSPs are pre-compiled:
...
[INFO] --- maven-scalate-plugin_2.10:1.6.1:precompile (default) @ web ---
[INFO] Precompiling Scalate Templates into Scala classes...
[INFO] processing /Users/dionis/projects/spring-mvc-java8-web-app-template/web/src/main/webapp/WEB-INF/views/scalate/main/person.ssp
[INFO] processing /Users/dionis/projects/spring-mvc-java8-web-app-template/web/src/main/webapp/WEB-INF/views/scalate/main/people.ssp
[INFO] processing /Users/dionis/projects/spring-mvc-java8-web-app-template/web/src/main/webapp/WEB-INF/scalate/layouts/default.ssp
...
So if anything has gone wrong and we have broken something that can be compiled, we will learn about it now, not after deployment at dev/qa/staging/production environment.
We used Twitter Bootstrap in the example, as I like it.
Adding new user
Users' list:
Editing a user:
Example code:
github.com/dargiri/spring-mvc-java8-web-app-template
As a free bonus:
The same on Java 7:
github.com/dargiri/spring-mvc-java-web-app-template
The same on Scala:
github.com/dargiri/spring-mvc-scala-web-app-template
If you are Still Reading It and Want to Fool Around with the Code
I prefer running under IDE, not using plug-ins for IDE.
So in web-app-launcher module we can see Launcher class.
If you’re using Idea everything will run with no trouble.
If you’re using Eclipse/Netbeans some manipulations are required.
For Eclipse you can download it with out-of-box JDK 8 support: www.eclipse.org/downloads/index-java8.php
P.P.S. Write code and best of luck!
You need to choose maven-profile build for the project.
In the Launcher class the variable MULTI_MODULE_DEFAULT_PATH value should be changed from «web/src/main/webapp» to "../web/src/main/webapp" or to the full path from your file system root.
Links
- Apache Maven — maven.apache.org/
- Scalate — scalate.fusesource.org/
- Scala — www.scala-lang.org/
- Apache Tomcat — tomcat.apache.org/
- Twitter Bootstrap — getbootstrap.com/
- Spring Data JPA — projects.spring.io/spring-data-jpa/
- Hibernate ORM — hibernate.org/orm/
- JDK 8 — www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
- Spring — projects.spring.io/spring-framework/
0 comments
Upload image