Commit 11d5639d authored by Supraja Chamarthy's avatar Supraja Chamarthy

Initial commit

parents
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
/target/
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>02-todo-web-application-h2</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="**/bower_components/*|**/node_modules/*|**/*.min.js" kind="src" path="src/main/webapp"/>
<classpathentry kind="src" path="target/m2e-wtp/web-resources"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>
<attribute name="hide" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="output" path=""/>
</classpath>
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="todo-web-application-h2">
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<property name="context-root" value="todo-web-application-h2"/>
<property name="java-output-path" value="/02-todo-web-application-h2/target/classes"/>
</wb-module>
</project-modules>
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="wst.jsdt.web"/>
<installed facet="java" version="1.8"/>
<installed facet="jst.web" version="4.0"/>
<installed facet="wst.jsdt.web" version="1.0"/>
</faceted-project>
org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
Window
\ No newline at end of file
disabled=06target
eclipse.preferences.version=1
FROM tomcat:8.0.51-jre8-alpine
EXPOSE 8080
RUN rm -rf /usr/local/tomcat/webapps/*
COPY target/*.war /usr/local/tomcat/webapps/ROOT.war
CMD ["catalina.sh","run"]
\ No newline at end of file
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: todo-web-application-h2
name: todo-web-application-h2
namespace: default
spec:
replicas: 2
minReadySeconds: 45
selector:
matchLabels:
app: todo-web-application-h2
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: todo-web-application-h2
spec:
containers:
- image: in28min/todo-web-application-h2:0.0.1-SNAPSHOT
imagePullPolicy: IfNotPresent
name: todo-web-application-h2
restartPolicy: Always
terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
labels: #PODS
app: todo-web-application-h2
name: todo-web-application-h2
namespace: default
spec:
ports:
- nodePort: 30702
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: todo-web-application-h2
sessionAffinity: ClientIP
type: LoadBalancer
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.in28minutes.springboot.web</groupId>
<artifactId>02-todo-web-application-h2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>todo-web-application-h2</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.6</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap-datepicker</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>1.9.1</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>todo-web-application-h2</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.6</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>in28min/${project.name}</repository>
<tag>${project.version}</tag>
<skipDockerInfo>true</skipDockerInfo>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestones</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestones</url>
</pluginRepository>
</pluginRepositories>
</project>
\ No newline at end of file
# Todo Web Application using Spring Boot and H2 In memory database
Run com.nisum.springboot.web.SpringBootFirstWebApplication as a Java Application.
Runs on default port of Spring Boot - 8080
## Can be run as a Jar or a WAR
`mvn clean install` generate a war which can deployed to your favorite web server.
We will deploy to Docker as a WAR
## Web Application
- http://localhost:8080/login with in28minutes/dummy as credentials
- You can add, delete and update your todos
- Spring Security is used to secure the application
- `com.nisum.springboot.web.security.SecurityConfiguration` contains the in memory security credential configuration.
## H2 Console
- http://localhost:8080/h2-console
- Use `jdbc:h2:mem:testdb` as JDBC URL
## Plugins
### Dockerfile Maven
- https://github.com/spotify/dockerfile-maven
```
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.6</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>${project.name}</repository>
<tag>${project.version}</tag>
<skipDockerInfo>true</skipDockerInfo>
</configuration>
</plugin>
```
### JIB
- https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#quickstart
- https://github.com/GoogleContainerTools/jib/blob/master/docs/faq.md
- `<useCurrentTimestamp>true</useCurrentTimestamp>` - https://github.com/GoogleContainerTools/jib/issues/413
```
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>1.6.1</version>
<configuration>
<from>
<image>tomcat:8.5-jre8-alpine</image>
</from>
<container>
<appRoot>/usr/local/tomcat/webapps/my-webapp</appRoot>
<creationTime>USE_CURRENT_TIMESTAMP</creationTime>
</container>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>dockerBuild</goal>
</goals>
</execution>
</executions>
</plugin>
```
\ No newline at end of file
package com.nisum.springboot.web;
import java.util.Arrays;
import java.util.stream.StreamSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.stereotype.Component;
@Component
public class EnvironmentConfigurationLogger {
private static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentConfigurationLogger.class);
@SuppressWarnings("rawtypes")
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
final Environment environment = event.getApplicationContext().getEnvironment();
LOGGER.info("====== Environment and configuration ======");
LOGGER.info("Active profiles: {}", Arrays.toString(environment.getActiveProfiles()));
final MutablePropertySources sources = ((AbstractEnvironment) environment).getPropertySources();
StreamSupport.stream(sources.spliterator(), false).filter(ps -> ps instanceof EnumerablePropertySource)
.map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()).flatMap(Arrays::stream).distinct()
.forEach(prop -> {
Object resolved = environment.getProperty(prop, Object.class);
if (resolved instanceof String) {
LOGGER.info("{} - {}", prop, environment.getProperty(prop));
} else {
LOGGER.info("{} - {}", prop, "NON-STRING-VALUE");
}
});
LOGGER.debug("===========================================");
}
}
package com.nisum.springboot.web;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan("com.nisum.springboot.web")
public class SpringBootFirstWebApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringBootFirstWebApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SpringBootFirstWebApplication.class, args);
}
}
\ No newline at end of file
package com.nisum.springboot.web.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@Controller("error")
public class ErrorController {
@ExceptionHandler(Exception.class)
public ModelAndView handleException
(HttpServletRequest request, Exception ex){
ModelAndView mv = new ModelAndView();
mv.addObject("exception", ex.getLocalizedMessage());
mv.addObject("url", request.getRequestURL());
mv.setViewName("error");
return mv;
}
}
package com.nisum.springboot.web.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class LogoutController {
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout(HttpServletRequest request,
HttpServletResponse response) {
Authentication authentication = SecurityContextHolder.getContext()
.getAuthentication();
if (authentication != null) {
new SecurityContextLogoutHandler().logout(request, response,
authentication);
}
return "redirect:/";
}
}
package com.nisum.springboot.web.controller;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.nisum.springboot.web.model.Todo;
import com.nisum.springboot.web.service.TodoRepository;
@Controller
public class TodoController {
@Autowired
TodoRepository repository;
@InitBinder
public void initBinder(WebDataBinder binder) {
// Date - dd/MM/yyyy
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
binder.registerCustomEditor(Date.class, new CustomDateEditor(
dateFormat, false));
}
@RequestMapping(value = "/list-todos", method = RequestMethod.GET)
public String showTodos(ModelMap model) {
String name = getLoggedInUserName(model);
model.put("todos", repository.findByUser(name));
//model.put("todos", service.retrieveTodos(name));
return "list-todos";
}
private String getLoggedInUserName(ModelMap model) {
Object principal = SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
return ((UserDetails) principal).getUsername();
}
return principal.toString();
}
@RequestMapping(value = "/add-todo", method = RequestMethod.GET)
public String showAddTodoPage(ModelMap model) {
model.addAttribute("todo", new Todo(0, getLoggedInUserName(model),
"Default Desc", new Date(), false));
return "todo";
}
@RequestMapping(value = "/delete-todo", method = RequestMethod.GET)
public String deleteTodo(@RequestParam int id) {
//if(id==1)
//throw new RuntimeException("Something went wrong");
repository.deleteById(id);
//service.deleteTodo(id);
return "redirect:/list-todos";
}
@RequestMapping(value = "/update-todo", method = RequestMethod.GET)
public String showUpdateTodoPage(@RequestParam int id, ModelMap model) {
Todo todo = repository.findById(id).get();
//Todo todo = service.retrieveTodo(id);
model.put("todo", todo);
return "todo";
}
@RequestMapping(value = "/update-todo", method = RequestMethod.POST)
public String updateTodo(ModelMap model, @Valid Todo todo,
BindingResult result) {
if (result.hasErrors()) {
return "todo";
}
todo.setUser(getLoggedInUserName(model));
repository.save(todo);
//service.updateTodo(todo);
return "redirect:/list-todos";
}
@RequestMapping(value = "/add-todo", method = RequestMethod.POST)
public String addTodo(ModelMap model, @Valid Todo todo, BindingResult result) {
if (result.hasErrors()) {
return "todo";
}
todo.setUser(getLoggedInUserName(model));
repository.save(todo);
/*service.addTodo(getLoggedInUserName(model), todo.getDesc(), todo.getTargetDate(),
false);*/
return "redirect:/list-todos";
}
}
package com.nisum.springboot.web.controller;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class WelcomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String showWelcomePage(ModelMap model) {
model.put("name", getLoggedinUserName());
return "welcome";
}
private String getLoggedinUserName() {
Object principal = SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
return ((UserDetails) principal).getUsername();
}
return principal.toString();
}
}
package com.nisum.springboot.web.model;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.Size;
@Entity
public class Todo {
@Id
@GeneratedValue
private int id;
private String user;
@Size(min=10, message="Enter at least 10 Characters...")
private String desc;
private Date targetDate;
private boolean isDone;
public Todo() {
super();
}
public Todo(int id, String user, String desc, Date targetDate,
boolean isDone) {
super();
this.id = id;
this.user = user;
this.desc = desc;
this.targetDate = targetDate;
this.isDone = isDone;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Date getTargetDate() {
return targetDate;
}
public void setTargetDate(Date targetDate) {
this.targetDate = targetDate;
}
public boolean isDone() {
return isDone;
}
public void setDone(boolean isDone) {
this.isDone = isDone;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Todo other = (Todo) obj;
if (id != other.id) {
return false;
}
return true;
}
@Override
public String toString() {
return String.format(
"Todo [id=%s, user=%s, desc=%s, targetDate=%s, isDone=%s]", id,
user, desc, targetDate, isDone);
}
}
\ No newline at end of file
package com.nisum.springboot.web.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
//Create User - in28Minutes/dummy
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("in28minutes").password("{noop}dummy")
.roles("USER", "ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login", "/h2-console/**").permitAll()
.antMatchers("/", "/*todo*/**").access("hasRole('USER')").and()
.formLogin();
http.csrf().disable();
http.headers().frameOptions().disable();
}
}
package com.nisum.springboot.web.service;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.nisum.springboot.web.model.Todo;
public interface TodoRepository extends JpaRepository<Todo, Integer> {
List<Todo> findByUser(String user);
}
\ No newline at end of file
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
logging.level.org.springframework.web=INFO
spring.jpa.show-sql=true
spring.h2.console.enabled=true
spring.h2.console.settings.web-allow-others=true
\ No newline at end of file
insert into TODO
values(10001, 'Learn Spring Boot', false, sysdate(), 'in28minutes');
insert into TODO
values(10002, 'Learn Angular JS', false, sysdate(), 'in28minutes');
insert into TODO
values(10003, 'Learn to Dance', false, sysdate(), 'in28minutes');
<script src="webjars/jquery/1.9.1/jquery.min.js"></script>
<script src="webjars/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script
src="webjars/bootstrap-datepicker/1.0.1/js/bootstrap-datepicker.js"></script>
<script>
$('#targetDate').datepicker({
format : 'dd/mm/yyyy'
});
</script>
</body>
</html>
\ No newline at end of file
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>First Web Application</title>
<link href="webjars/bootstrap/3.3.6/css/bootstrap.min.css"
rel="stylesheet">
</head>
<body>
<nav role="navigation" class="navbar navbar-default">
<div class="">
<a href="http://www.in28minutes.com" class="navbar-brand">in28Minutes</a>
</div>
<div class="navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="./">Home</a></li>
<li><a href="./list-todos">Todos</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="./logout">Logout</a></li>
</ul>
</div>
</nav>
<%@ include file="common/header.jspf"%>
<%@ include file="common/navigation.jspf"%>
<div class="container">
An exception occurred! Please contact Support!
</div>
<%@ include file="common/footer.jspf"%>
\ No newline at end of file
<%@ include file="common/header.jspf" %>
<%@ include file="common/navigation.jspf" %>
<div class="container">
<table class="table table-striped">
<caption>Your todos are</caption>
<thead>
<tr>
<th>Description</th>
<th>Target Date</th>
<th>Is it Done?</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<c:forEach items="${todos}" var="todo">
<tr>
<td>${todo.desc}</td>
<td><fmt:formatDate value="${todo.targetDate}" pattern="dd/MM/yyyy"/></td>
<td>${todo.done}</td>
<td><a type="button" class="btn btn-success"
href="./update-todo?id=${todo.id}">Update</a></td>
<td><a type="button" class="btn btn-warning"
href="./delete-todo?id=${todo.id}">Delete</a></td>
</tr>
</c:forEach>
</tbody>
</table>
<div>
<a class="button" href="./add-todo">Add a Todo</a>
</div>
</div>
<%@ include file="common/footer.jspf" %>
\ No newline at end of file
<%@ include file="common/header.jspf" %>
<%@ include file="common/navigation.jspf" %>
<div class="container">
<form:form method="post" modelAttribute="todo">
<form:hidden path="id" />
<fieldset class="form-group">
<form:label path="desc">Description</form:label>
<form:input path="desc" type="text" class="form-control"
required="required" />
<form:errors path="desc" cssClass="text-warning" />
</fieldset>
<fieldset class="form-group">
<form:label path="targetDate">Target Date</form:label>
<form:input path="targetDate" type="text" class="form-control"
required="required" />
<form:errors path="targetDate" cssClass="text-warning" />
</fieldset>
<button type="submit" class="btn btn-success">Add</button>
</form:form>
</div>
<%@ include file="common/footer.jspf" %>
\ No newline at end of file
<%@ include file="common/header.jspf"%>
<%@ include file="common/navigation.jspf"%>
<div class="container">
Welcome ${name}!! <a href="./list-todos">Click here</a> to manage your
todo's.
</div>
<%@ include file="common/footer.jspf"%>
\ No newline at end of file
package com.nisum.springboot.web;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootFirstWebApplicationTests {
@Test
public void contextLoads() {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment