Another Example with Spring(MVC) + Maven + Jetty + JSP + MySQL Java Web App..

Yet another tiny-miny web page I made for fun!

Directory Layout


pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>biz.tugay.booksSpringOne</groupId>
    <artifactId>books-spring-one</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>books-spring-one Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.35</version>
        </dependency>
    </dependencies>
 
    <properties>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
    <build>
        <finalName>books-spring-one</finalName>
        <plugins>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.2.1.v20140609</version>
                <configuration>
                    <scanIntervalSeconds>2</scanIntervalSeconds>
                    <webApp>
                        <contextPath>/</contextPath>
                    </webApp>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

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_3_0.xsd"
         version="3.0">
 
    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <url-pattern>*.jspf</url-pattern>
            <page-encoding>UTF-8</page-encoding>
            <scripting-invalid>true</scripting-invalid>
            <include-prelude>/WEB-INF/views/header.jsp</include-prelude>
            <include-coda>/WEB-INF/views/footer.jsp</include-coda>
            <trim-directive-whitespaces>true</trim-directive-whitespaces>
            <default-content-type>text/html</default-content-type>
        </jsp-property-group>
    </jsp-config>
</web-app>

header.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>My Books App!!!</title>
    <!-- Bootstrap Core CSS -->
    <link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
    <!-- Custom CSS -->
    <link href="<c:url value="/resources/css/simple-sidebar.css"/>" rel="stylesheet">
</head>
 
<body>
 
<div id="wrapper">
    <!-- Sidebar -->
    <div id="sidebar-wrapper">
        <ul class="sidebar-nav">
            <li class="sidebar-brand">
                <a href="<c:url value="/"/>">
                    Home
                </a>
            </li>
            <li>
                <a href="<c:url value="/allbooks"/>">All Books</a>
            </li>
        </ul>
    </div>
    <!-- /#sidebar-wrapper -->
 
    <!-- Page Content -->
    <div id="page-content-wrapper">
        <div class="container-fluid">
            <div class="row">
                <div class="col-lg-12">

footer.jsp
</div>
</div>
</div>
</div>
<!-- /#page-content-wrapper -->
</div>
<!-- /#wrapper -->
<script src="<c:url value="/resources/js/jquery.js"/>"></script>
<script src="<c:url value="/resources/js/bootstrap.min.js"/>"></script>
</body>
</html>

welcome.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<h1>Books Application</h1>
<p>
    Another example I made just for fun...
</p>

allBooks.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
<%--@elvariable id="allBooks" type="java.util.List<biz.tugay.booksspringone.model.Book>"--%>
 
<c:forEach items="${allBooks}" var="book">
    <div class="span6" style="margin-bottom: 50px; background-color: lightgray">
        <h4 style="color: darkblue">${book.bookTitle}</h4>
        <h5>${book.publisherName}</h5>
        <a href="<c:url value="/byAuthor">
            <c:param name="firstName" value="${book.authors[0].firstName}"/>
            <c:param name="lastName" value="${book.authors[0].lastName}"/>
        </c:url>"
                >
            <span>${book.authors[0].lastName}&nbsp;${book.authors[0].firstName}</span>
        </a>
        <br/>
        <c:if test="${book.fileName != null}">
            <img src="<c:url value="/resources/img/${book.fileName}"/>">
        </c:if>
        <c:if test="${book.fileName == null}">
            <img src="<c:url value="/resources/img/NoCover.jpg"/>">
        </c:if>
    </div>
</c:forEach>

byAuthor.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
<%--@elvariable id="byAuthor" type="java.util.List<biz.tugay.booksspringone.model.Book>"--%>
 
<c:forEach items="${byAuthor}" var="book">
    <div class="span6" style="margin-bottom: 50px; background-color: lightgray">
        <h4 style="color: darkblue">${book.bookTitle}</h4>
        <h5>${book.publisherName}</h5>
        <span>${book.authors[0].lastName}&nbsp;${book.authors[0].firstName}</span>
        <br/>
        <c:if test="${book.fileName != null}">
            <img src="<c:url value="/resources/img/${book.fileName}"/>">
        </c:if>
        <c:if test="${book.fileName == null}">
            <img src="<c:url value="/resources/img/NoCover.jpg"/>">
        </c:if>
    </div>
</c:forEach>

BaseDao.java
package biz.tugay.booksspringone.dao;
/* User: koray@tugay.biz Date: 03/07/15 Time: 13:55 */
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
 
public abstract class BaseDao {
 
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }
 
    protected Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/books", "root", "");
    }
 
    protected void closeConnection(Connection connection) {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

BookDao.java
package biz.tugay.booksspringone.dao;
/* User: koray@tugay.biz Date: 03/07/15 Time: 13:53 */
 
import biz.tugay.booksspringone.model.Book;
 
import java.util.List;
 
public interface BookDao {
    public List<Book> findAllBooks();
    public List<Book> findBooksByAuthor(String authorFirstName, String authorLastName);
}

BookDaoImpl.java
package biz.tugay.booksspringone.dao;
/* User: koray@tugay.biz Date: 03/07/15 Time: 13:54 */
 
import biz.tugay.booksspringone.model.Author;
import biz.tugay.booksspringone.model.Book;
import org.springframework.stereotype.Repository;
 
import java.util.List;
import java.sql.*;
import java.util.ArrayList;
 
@Repository
public class BookDaoImpl extends BaseDao implements BookDao {
 
    @Override
    public List<Book> findAllBooks() {
        List<Book> books = new ArrayList<>();
        String sql = "SELECT * FROM book INNER JOIN author ON book.id = author.book_id";
        Connection connection = null;
        execute(books, sql, connection);
        return books;
    }
 
    @Override
    public List<Book> findBooksByAuthor(String authorFirstName, String authorLastName) {
        List<Book> books = new ArrayList<>();
        String sql = "SELECT * FROM BOOK INNER JOIN AUTHOR ON BOOK.ID = AUTHOR.BOOK_ID WHERE AUTHOR.FIRST_NAME = '"
                + authorFirstName + "' AND AUTHOR.LAST_NAME = '" + authorLastName + "'";
        Connection connection = null;
        execute(books, sql, connection);
        return books;
    }
 
    private void execute(List<Book> books, String sql, Connection connection) {
        try {
            connection = getConnection();
            ResultSet resultSet = connection.prepareStatement(sql).executeQuery();
            while (resultSet.next()) {
                books.add(createBookFromResult(resultSet));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeConnection(connection);
        }
    }
 
    protected Book createBookFromResult(ResultSet resultSet)
            throws SQLException {
        List<Author> authorList = new ArrayList<>();
        Book book = new Book();
        Author author = new Author();
        book.setId(resultSet.getLong("id"));
        book.setBookTitle(resultSet.getString("book_title"));
        book.setCategoryId(resultSet.getLong("category_id"));
        book.setFileName(resultSet.getString("FILE_NAME"));
        author.setBookId(resultSet.getLong("book_Id"));
        author.setFirstName(resultSet.getString("first_name"));
        author.setLastName(resultSet.getString("last_name"));
        authorList.add(author);
        book.setAuthors(authorList);
        book.setPublisherName(resultSet.getString("publisher"));
        return book;
    }
}

BookService.java
package biz.tugay.booksspringone.service;
/* User: koray@tugay.biz Date: 04/07/15 Time: 07:19 */
 
import biz.tugay.booksspringone.dao.BookDao;
import biz.tugay.booksspringone.model.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import java.util.List;
 
@Service
public class BookService {
 
    private BookDao bookDao;
 
    public List<Book> findAllBooks() {
        List<Book> allBooks = bookDao.findAllBooks();
        return allBooks;
    }
 
    public List<Book> booksByAuthor(String firstName, String lastName) {
        return bookDao.findBooksByAuthor(firstName, lastName);
    }
 
    @Autowired
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

BookController.java
package biz.tugay.booksspringone.controller;
/* User: koray@tugay.biz Date: 03/07/15 Time: 11:48 */
 
import biz.tugay.booksspringone.model.Book;
import biz.tugay.booksspringone.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
 
import java.util.List;
 
@Controller
public class BooksController {
 
    private BookService bookService;
 
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView welcome() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("welcome");
        return modelAndView;
    }
 
    @RequestMapping(value = "/allbooks", method = RequestMethod.GET)
    public ModelAndView allBooks() {
        List<Book> allBooks = bookService.findAllBooks();
        ModelAndView allBooksModelAndView = new ModelAndView();
        allBooksModelAndView.addObject("allBooks", allBooks);
        allBooksModelAndView.setViewName("allBooks");
        return allBooksModelAndView;
    }
 
    @RequestMapping(value = "/byAuthor", method = RequestMethod.GET)
    public ModelAndView byAuthor(@RequestParam String firstName, @RequestParam String lastName) {
        List<Book> byAuthor = bookService.booksByAuthor(firstName, lastName);
        ModelAndView allBooksModelAndView = new ModelAndView();
        allBooksModelAndView.addObject("byAuthor", byAuthor);
        allBooksModelAndView.setViewName("byAuthor");
        return allBooksModelAndView;
    }
 
    @Autowired
    public void setBookService(BookService bookService) {
        this.bookService = bookService;
    }
}

Bootstrap.java
package biz.tugay.booksspringone.config;
/* User: koray@tugay.biz Date: 03/07/15 Time: 11:41 */
 
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
 
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
 
@SuppressWarnings("unused")
public class Bootstrap implements WebApplicationInitializer {
 
    @Override
    public void onStartup(ServletContext container) throws ServletException {
 
        container.getServletRegistration("default").addMapping("/resources/*");
 
        AnnotationConfigWebApplicationContext rootContext
                = new AnnotationConfigWebApplicationContext();
        rootContext.register(RootContextConfiguration.class);
        container.addListener(new ContextLoaderListener(rootContext));
 
        AnnotationConfigWebApplicationContext servletContext =
                new AnnotationConfigWebApplicationContext();
        servletContext.register(ServletContextConfiguration.class);
 
        //This is for bootstrapping Spring:
        ServletRegistration.Dynamic dispatcher =
                container.addServlet("springDispatcher", new DispatcherServlet(servletContext));
 
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}

RootContextConfiguration.java
package biz.tugay.booksspringone.config;
/* User: koray@tugay.biz Date: 03/07/15 Time: 11:38 */
 
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
 
@Configuration
@ComponentScan(
        basePackages = "biz.tugay.booksspringone",
        excludeFilters = @ComponentScan.Filter(Controller.class)
)
 
public class RootContextConfiguration {
}

ServletContextConfiguration.java
package biz.tugay.booksspringone.config;
/* User: koray@tugay.biz Date: 03/07/15 Time: 11:39 */
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
 
@Configuration
@EnableWebMvc
@ComponentScan(
        basePackages = "biz.tugay.booksspringone.controller",
        useDefaultFilters = false,
        includeFilters = @ComponentScan.Filter(Controller.class)
)
public class ServletContextConfiguration {
 
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }
}