├── LICENSE
├── README.md
├── WorkInProgress.md
├── pom.xml
├── src
└── main
│ ├── java
│ └── com
│ │ └── in28minutes
│ │ ├── model
│ │ └── Todo.java
│ │ ├── struts
│ │ ├── EditAddTodoAction.java
│ │ ├── ListTodosAction.java
│ │ ├── ShowTodoAction.java
│ │ └── WelcomeAction.java
│ │ └── todo
│ │ └── service
│ │ └── TodoService.java
│ ├── resources
│ ├── log4j.properties
│ ├── messages_en.properties
│ ├── messages_fr.properties
│ └── struts.xml
│ └── webapp
│ └── WEB-INF
│ ├── views
│ ├── common
│ │ ├── footer.jspf
│ │ ├── header.jspf
│ │ └── navigation.jspf
│ ├── error.jsp
│ └── user
│ │ ├── customized-error.jsp
│ │ ├── list-todos.jsp
│ │ ├── todo.jsp
│ │ └── welcome.jsp
│ └── web.xml
└── workInProgress.zip
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Struts Tutorial For Beginners
2 | Struts Tutorial For Beginners in 25 Easy Steps
3 |
4 | # Todo
5 | - Delete todo
6 | - Rest Service
7 | - Internationalization
8 | - Spring Security (remove hardcoding of userName)
9 | - JSR Validation.The JSR 303 and JSR 349 defines specification for the Bean Validation API (version 1.0 and 1.1, respectively), and Hibernate Validator is the reference implementation.
10 |
11 | # First Struts 2 Application in 25 Easy Steps
12 |
13 | ## Struts 2 Tutorial for Beginners
14 |
15 | ## Installing Eclipse and Java
16 | https://github.com/in28minutes/SpringIn28Minutes/blob/master/InstallationGuide-JavaEclipseAndMaven_v2.pdf
17 |
18 | ## Course Overview
19 |
20 | ### Steps 1 to 7 : Build a normal Web Application
21 | - Understand Basics of HTTP - HttpRequest - GET/POST, Request Parameters
22 | - Introduction to JSP, Servlets, JSTL, Scriptlets and EL.
23 | - Understand Basics of using Maven, Tomcat and Eclipse
24 |
25 | ### Steps 11 to XX : Use Struts 2 to Build Your First Web Application
26 | - struts-default, Interceptors, @Action, @Namespace
27 | - Forms - DataBinding, Validation
28 | - Annotation based approach
29 | - Bootstrap to style the page
30 | - Spring Security
31 | - Internationalization - Validation Messages
32 | - Exception Handling
33 | - Basic REST Services
34 | - Logout
35 |
36 | ## Our Approach
37 | - Instead of taking traditional approach, feature-by-feature, we will take a problem-solution step-by-step approach.
38 | - We will use 80-20 Rule. We discuss the 20% things used 80% of time in depth. We touch upon other things briefly equipping you with enough knowledge to find out more on your own.
39 | - We will be developing a demo application in the course, which could be reused in your projects, saving hours of your effort.
40 | - All the code is available on Github, step by step.
41 | - We will use Struts 2.3
42 |
43 | ## Expectations
44 | - For taking this course, you should already know Java.
45 | - We expect NO prior experience with web development using Java.
46 | - We expect NO prior experience with Struts or Spring Security.
47 |
48 | ## Step wise details
49 | - Step01.md : Up and running with a web app in Tomcat
50 | - Step02.md : First JSP
51 | - Step03.md : Adding a GET Parameter name
52 | - Step04.md : Adding another Get Parameter Password
53 | - Step05.md : Lets add a form
54 | - Step06.md : New Form and doPost
55 | - Step07.md : Adding Password, validation of userid/password
56 | ...
57 | ...
58 | ...
59 | ...
60 |
61 | ## Exercises
62 | - Functionality to mark a Todo as complete
63 |
64 | ## Future Things To Do
65 | - Unit Tests - WTF - why are they not here in the first set?
66 |
67 | ### Other Courses
68 |
69 | - [Check out all our courses with 100,000 Students](https://courses.in28minutes.com/courses)
70 | - [25 Videos and Articles for Beginners on Spring Boot](http://www.springboottutorial.com/spring-boot-tutorials-for-beginners)
71 | - Our Best Courses with 66,000 Students and 4,000 5-Star Ratings
72 | * [Java Interview Guide : 200+ Interview Questions and Answers](https://www.udemy.com/java-interview-questions-and-answers/?couponCode=JAVA_INTER_GIT)
73 | * [First Web Application with Spring Boot](https://www.udemy.com/spring-boot-first-web-application/?couponCode=SPRING-BOOT-1-GIT)
74 | * [Spring Boot Tutorial For Beginners](https://www.udemy.com/spring-boot-tutorial-for-beginners/?couponCode=SPRING-BOOT-GIT)
75 | * [Mockito Tutorial : Learn mocking with 25 Junit Examples](https://www.udemy.com/mockito-tutorial-with-junit-examples/?couponCode=MOCKITO_GIT)
76 | * [Java EE Made Easy - Patterns, Architecture and Frameworks](https://www.udemy.com/java-ee-design-patterns-architecture-and-frameworks/?couponCode=EEPATTERNS-GIT)
77 | * [Spring MVC For Beginners : Build Java Web App in 25 Steps](https://www.udemy.com/spring-mvc-tutorial-for-beginners-step-by-step/?couponCode=SPRINGMVC-GIT)
78 | * [JSP Servlets For Beginners : Build Java Web App in 25 Steps](https://www.udemy.com/learn-java-servlets-and-jsp-web-application-in-25-steps/?couponCode=JSPSRVLT-GIT)
79 | * [Maven Tutorial - Manage Java Dependencies in 25 Steps](https://www.udemy.com/learn-maven-java-dependency-management-in-20-steps/?couponCode=MAVEN_GIT)
80 | * [Java OOPS in 1 Hours](https://www.udemy.com/learn-object-oriented-programming-in-java/?couponCode=OOPS-GIT)
81 | * [C Puzzle for Interview](https://www.udemy.com/c-puzzles-for-beginners/?couponCode=CPUZZLES-GIT)
82 |
83 | ### Useful Links
84 | - [Our Website](http://www.in28minutes.com)
85 | - [Facebook](http://facebook.com/in28minutes)
86 | - [Twitter](http://twitter.com/in28minutes)
87 | - [Google Plus](https://plus.google.com/u/3/110861829188024231119)
88 |
--------------------------------------------------------------------------------
/WorkInProgress.md:
--------------------------------------------------------------------------------
1 | ## Files List
2 | ### pom.xml
3 | ```
4 |
6 | 4.0.0
7 | com.in28minutes
8 | in28Minutes-struts
9 | 0.0.1-SNAPSHOT
10 | war
11 |
12 |
13 |
14 | javax
15 | javaee-web-api
16 | 6.0
17 | provided
18 |
19 |
20 |
21 | org.apache.struts
22 | struts2-core
23 | 2.3.24.1
24 |
25 |
26 |
27 |
28 | org.apache.struts
29 | struts2-convention-plugin
30 | 2.3.24.1
31 |
32 |
33 |
34 | javax.servlet
35 | jstl
36 | 1.2
37 |
38 |
39 |
40 | org.webjars
41 | bootstrap
42 | 3.3.6
43 |
44 |
45 | org.webjars
46 | jquery
47 | 1.9.1
48 |
49 |
50 |
51 | org.webjars
52 | bootstrap-datepicker
53 | 1.0.1
54 |
55 |
56 |
57 | org.hibernate
58 | hibernate-validator
59 | 5.0.2.Final
60 |
61 |
62 |
63 | log4j
64 | log4j
65 | 1.2.17
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.apache.maven.plugins
74 | maven-compiler-plugin
75 | 3.2
76 |
77 | true
78 | 1.8
79 | 1.8
80 | true
81 |
82 |
83 |
84 | org.apache.tomcat.maven
85 | tomcat7-maven-plugin
86 | 2.2
87 |
88 | /
89 | true
90 |
91 |
92 |
93 |
94 |
95 |
96 | ```
97 | ### src/main/java/com/in28minutes/model/Todo.java
98 | ```
99 | package com.in28minutes.model;
100 |
101 | import java.util.Date;
102 |
103 | import javax.validation.constraints.Size;
104 |
105 | public class Todo {
106 | private int id;
107 |
108 | private String user;
109 |
110 | @Size(min = 10, message = "Enter atleast 10 Characters.")
111 | private String desc;
112 |
113 | private Date targetDate;
114 | private boolean isDone;
115 |
116 | public Todo() {
117 | super();
118 | }
119 |
120 | public Todo(int id, String user, String desc, Date targetDate,
121 | boolean isDone) {
122 | super();
123 | this.id = id;
124 | this.user = user;
125 | this.desc = desc;
126 | this.targetDate = targetDate;
127 | this.isDone = isDone;
128 | }
129 |
130 | public int getId() {
131 | return id;
132 | }
133 |
134 | public void setId(int id) {
135 | this.id = id;
136 | }
137 |
138 | public String getUser() {
139 | return user;
140 | }
141 |
142 | public void setUser(String user) {
143 | this.user = user;
144 | }
145 |
146 | public String getDesc() {
147 | return desc;
148 | }
149 |
150 | public void setDesc(String desc) {
151 | this.desc = desc;
152 | }
153 |
154 | public Date getTargetDate() {
155 | return targetDate;
156 | }
157 |
158 | public void setTargetDate(Date targetDate) {
159 | this.targetDate = targetDate;
160 | }
161 |
162 | public boolean isDone() {
163 | return isDone;
164 | }
165 |
166 | public void setDone(boolean isDone) {
167 | this.isDone = isDone;
168 | }
169 |
170 | @Override
171 | public int hashCode() {
172 | final int prime = 31;
173 | int result = 1;
174 | result = prime * result + id;
175 | return result;
176 | }
177 |
178 | @Override
179 | public boolean equals(Object obj) {
180 | if (this == obj)
181 | return true;
182 | if (obj == null)
183 | return false;
184 | if (getClass() != obj.getClass())
185 | return false;
186 | Todo other = (Todo) obj;
187 | if (id != other.id)
188 | return false;
189 | return true;
190 | }
191 |
192 | @Override
193 | public String toString() {
194 | return String.format(
195 | "Todo [id=%s, user=%s, desc=%s, targetDate=%s, isDone=%s]", id,
196 | user, desc, targetDate, isDone);
197 | }
198 |
199 | }
200 | ```
201 | ### src/main/java/com/in28minutes/struts/EditAddTodoAction.java
202 | ```
203 | package com.in28minutes.struts;
204 |
205 | import org.apache.struts2.convention.annotation.Action;
206 | import org.apache.struts2.convention.annotation.Namespace;
207 | import org.apache.struts2.convention.annotation.Result;
208 | import org.apache.struts2.convention.annotation.ResultPath;
209 |
210 | import com.in28minutes.model.Todo;
211 | import com.in28minutes.todo.service.TodoService;
212 |
213 | @Namespace("/user")
214 | @ResultPath(value = "/WEB-INF/views/")
215 | public class EditAddTodoAction {
216 | private Todo todo;
217 |
218 | @Action(value = "edit-todo", results = { @Result(name = "success", type = "redirect", location = "list-todos") })
219 | public String execute() {
220 | TodoService todoService = new TodoService();
221 | if (todo.getId() > 0) {
222 | todo.setUser("in28Minutes");
223 | todoService.updateTodo(todo);
224 | } else {
225 | todoService.addTodo("in28Minutes", todo.getDesc(),
226 | todo.getTargetDate(), false);
227 |
228 | }
229 | return "success";
230 | }
231 |
232 | public Todo getTodo() {
233 | return todo;
234 | }
235 |
236 | public void setTodo(Todo todo) {
237 | this.todo = todo;
238 | }
239 | }
240 | ```
241 | ### src/main/java/com/in28minutes/struts/ListTodosAction.java
242 | ```
243 | package com.in28minutes.struts;
244 |
245 | import java.util.ArrayList;
246 | import java.util.List;
247 |
248 | import org.apache.struts2.convention.annotation.Action;
249 | import org.apache.struts2.convention.annotation.ExceptionMapping;
250 | import org.apache.struts2.convention.annotation.ExceptionMappings;
251 | import org.apache.struts2.convention.annotation.Namespace;
252 | import org.apache.struts2.convention.annotation.Result;
253 | import org.apache.struts2.convention.annotation.ResultPath;
254 |
255 | import com.in28minutes.model.Todo;
256 | import com.in28minutes.todo.service.TodoService;
257 |
258 | @Namespace("/user")
259 | @ResultPath(value = "/WEB-INF/views/")
260 | @ExceptionMappings({ @ExceptionMapping(exception = "java.lang.Exception", result = "error") })
261 | public class ListTodosAction {
262 | private List todos = new ArrayList();
263 |
264 | public List getTodos() {
265 | return todos;
266 | }
267 |
268 | @Action(value = "list-todos", results = {
269 | @Result(name = "success", location = "list-todos.jsp"),
270 | @Result(name = "error", location = "customized-error.jsp") })
271 | public String execute() {
272 | todos = new TodoService().retrieveTodos("in28Minutes");
273 | return "success";
274 | }
275 | }
276 | ```
277 | ### src/main/java/com/in28minutes/struts/ShowTodoAction.java
278 | ```
279 | package com.in28minutes.struts;
280 |
281 | import java.util.Date;
282 |
283 | import org.apache.struts2.convention.annotation.Action;
284 | import org.apache.struts2.convention.annotation.Namespace;
285 | import org.apache.struts2.convention.annotation.Result;
286 | import org.apache.struts2.convention.annotation.ResultPath;
287 |
288 | import com.in28minutes.model.Todo;
289 | import com.in28minutes.todo.service.TodoService;
290 |
291 | @Namespace("/user")
292 | @ResultPath(value = "/WEB-INF/views/")
293 | public class ShowTodoAction {
294 | private int id = 0;
295 |
296 | private Todo todo = new Todo(0, "in28Minutes", "Learn Spring MVC",
297 | new Date(), false);
298 |
299 | @Action(value = "show-todo", results = { @Result(name = "success", location = "todo.jsp") })
300 | public String execute() {
301 | if (id > 0) {
302 | todo = new TodoService().retrieveTodo(id);
303 | }
304 | return "success";
305 | }
306 |
307 | public Todo getTodo() {
308 | return todo;
309 | }
310 |
311 | public int getId() {
312 | return id;
313 | }
314 |
315 | public void setId(int id) {
316 | this.id = id;
317 | }
318 | }
319 | ```
320 | ### src/main/java/com/in28minutes/struts/WelcomeAction.java
321 | ```
322 | package com.in28minutes.struts;
323 |
324 | import org.apache.struts2.convention.annotation.Action;
325 | import org.apache.struts2.convention.annotation.Namespace;
326 | import org.apache.struts2.convention.annotation.Result;
327 | import org.apache.struts2.convention.annotation.ResultPath;
328 |
329 | @Namespace("/user")
330 | @ResultPath(value = "/WEB-INF/views/")
331 | public class WelcomeAction {
332 | @Action(value = "welcome", results = { @Result(name = "success", location = "welcome.jsp") })
333 | public String execute() {
334 | return "success";
335 | }
336 | }
337 | ```
338 | ### src/main/java/com/in28minutes/todo/service/TodoService.java
339 | ```
340 | package com.in28minutes.todo.service;
341 |
342 | import java.util.ArrayList;
343 | import java.util.Date;
344 | import java.util.Iterator;
345 | import java.util.List;
346 |
347 | import com.in28minutes.model.Todo;
348 |
349 | public class TodoService {
350 | private static List todos = new ArrayList();
351 | private static int todoCount = 3;
352 |
353 | static {
354 | todos.add(new Todo(1, "in28Minutes", "Learn Spring MVC", new Date(),
355 | false));
356 | todos.add(new Todo(2, "in28Minutes", "Learn Struts", new Date(), false));
357 | todos.add(new Todo(3, "in28Minutes", "Learn Hibernate", new Date(),
358 | false));
359 | }
360 |
361 | public List retrieveTodos(String user) {
362 | List filteredTodos = new ArrayList();
363 | for (Todo todo : todos) {
364 | if (todo.getUser().equals(user))
365 | filteredTodos.add(todo);
366 | }
367 | return filteredTodos;
368 | }
369 |
370 | public Todo retrieveTodo(int id) {
371 | for (Todo todo : todos) {
372 | if (todo.getId() == id)
373 | return todo;
374 | }
375 | return null;
376 | }
377 |
378 | public void updateTodo(Todo todo) {
379 | todos.remove(todo);
380 | todos.add(todo);
381 | }
382 |
383 | public void addTodo(String name, String desc, Date targetDate,
384 | boolean isDone) {
385 | todos.add(new Todo(++todoCount, name, desc, targetDate, isDone));
386 | }
387 |
388 | public void deleteTodo(int id) {
389 | Iterator iterator = todos.iterator();
390 | while (iterator.hasNext()) {
391 | Todo todo = iterator.next();
392 | if (todo.getId() == id) {
393 | iterator.remove();
394 | }
395 | }
396 | }
397 | }
398 | ```
399 | ### src/main/resources/log4j.properties
400 | ```
401 | log4j.rootLogger=DEBUG, Appender1
402 |
403 | log4j.appender.Appender1=org.apache.log4j.ConsoleAppender
404 | log4j.appender.Appender1.layout=org.apache.log4j.PatternLayout
405 | log4j.appender.Appender1.layout.ConversionPattern=%-7p %d [%t] %c %x - %m%n
406 |
407 | ```
408 | ### src/main/resources/messages_en.properties
409 | ```
410 | welcome.message=Welcome in English
411 | todo.caption= Todo Caption in English
412 | ```
413 | ### src/main/resources/messages_fr.properties
414 | ```
415 | welcome.message=Welcome in French
416 | todo.caption= Todo Caption in French
417 | ```
418 | ### src/main/resources/struts.xml
419 | ```
420 |
421 |
422 |
425 |
426 |
427 |
428 | /Error.jsp
429 |
430 |
431 |
432 |
434 |
435 |
436 |
437 |
438 | ```
439 | ### src/main/webapp/WEB-INF/views/common/footer.jspf
440 | ```
441 |
442 |
443 |
444 |
446 |
447 |