Spring: Adding one record to a List suddenly creates a duplicate
To pick up Spring, I'm playing around with very simple pages to understand the annotations and the behaviors of Spring in general. To be precise, I created a page to show a list of Task
and another page to add a new Task
. I used @SessionAttibutes
to save the list of Task in the session instead of calling a service to retrieve a full list of Task
everytime I access the task list page.
This is my TaskService
@Service
public class TaskService {
private List<Task> taskCache = new ArrayList<Task>();
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return taskCache;
}
public Task addTask(String title, String desc, Date targetDate) {
Task newTask = new Task(title, desc, targetDate);
taskCache.add(newTask);
return newTask;
}
}
This is my TaskController
@Controller
@SessionAttributes("taskList")
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/task-view")
public String showTaskList() {
return "task/view";
}
@GetMapping("/task-add")
public String showAddTaskForm(@ModelAttribute("task") Task newTask) {
return "task/add";
}
@PostMapping("/task-add")
public String addTask(ModelMap model, @ModelAttribute("task") Task newTask, @ModelAttribute("taskList") List<Task> taskList) {
System.out.println("ADDING NEW TASK: " + taskList.size());
taskList.add(taskService.addTask(newTask.getTitle(), newTask.getDesc(), new Date()));
System.out.println("DONE ADDING NEW TASK: " + taskList.size());
return "redirect:/task-view";
}
@ModelAttribute("taskList")
public List<Task> taskList() {
System.out.println("CALLING TASK SERVICE TO GET LIST OF TASKS");
return taskService.retrieveTasks();
}
}
This is my view.jsp
<html>
<head>
<title>Task Page</title>
</head>
<body>
This is your task list:
${taskList}
<div>
<a href="task-add">Add a task</a>
</div>
</body>
</html>
This is my add.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<title>Task Page</title>
</head>
<body>
<form:form method="POST" action="/task-add" modelAttribute="task">
<div>
<form:label path="title">Title</form:label>
<form:input path="title" />
</div>
<div>
<form:label path="desc">Description</form:label>
<form:input path="desc" />
</div>
<div>
<input type="submit" value="Add">
</div>
</form:form>
</body>
</html>
In term of the session-scoped attribute, it's working as I expect. The TaskService.retrieveTasks()
function is only called the 1st time I access the view.jsp
. Subsequently, the same list of task is pulled from the Session.
The problem is when I try to add two new Task
on the add.jsp
page, I saw the following lines in the console.
CALLING TASK SERVICE TO GET LIST OF TASKS
GETTING TASK LIST FOR THE FIRST TIME
ADDING NEW TASK: 0
DONE ADDING NEW TASK: 2
ADDING NEW TASK: 2
DONE ADDING NEW TASK: 4
The 1st two lines were printed when I accessed the view.jsp
for the 1st time, which is right. However, I have no idea what's happening between the ADDING NEW TASK
and DONE ADDING NEW TASK
lines. I'd be very grateful if someone could explain to me why the line below is adding a duplicate in my list of Task
taskList.add(taskService.addTask(newTask.getTitle(), newTask.getDesc(), new Date()));
I also tried to remove the taskList.add()
portion and only made a service call to taskService.addTask()
. In this case, there's no duplicate and my taskList
is updated with one new record. However, I don't understand how the taskService
could indirectly modify my taskList
when there's no injection in the TaskService
class.
Did I miss something?
java spring spring-mvc spring-boot session
add a comment |
To pick up Spring, I'm playing around with very simple pages to understand the annotations and the behaviors of Spring in general. To be precise, I created a page to show a list of Task
and another page to add a new Task
. I used @SessionAttibutes
to save the list of Task in the session instead of calling a service to retrieve a full list of Task
everytime I access the task list page.
This is my TaskService
@Service
public class TaskService {
private List<Task> taskCache = new ArrayList<Task>();
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return taskCache;
}
public Task addTask(String title, String desc, Date targetDate) {
Task newTask = new Task(title, desc, targetDate);
taskCache.add(newTask);
return newTask;
}
}
This is my TaskController
@Controller
@SessionAttributes("taskList")
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/task-view")
public String showTaskList() {
return "task/view";
}
@GetMapping("/task-add")
public String showAddTaskForm(@ModelAttribute("task") Task newTask) {
return "task/add";
}
@PostMapping("/task-add")
public String addTask(ModelMap model, @ModelAttribute("task") Task newTask, @ModelAttribute("taskList") List<Task> taskList) {
System.out.println("ADDING NEW TASK: " + taskList.size());
taskList.add(taskService.addTask(newTask.getTitle(), newTask.getDesc(), new Date()));
System.out.println("DONE ADDING NEW TASK: " + taskList.size());
return "redirect:/task-view";
}
@ModelAttribute("taskList")
public List<Task> taskList() {
System.out.println("CALLING TASK SERVICE TO GET LIST OF TASKS");
return taskService.retrieveTasks();
}
}
This is my view.jsp
<html>
<head>
<title>Task Page</title>
</head>
<body>
This is your task list:
${taskList}
<div>
<a href="task-add">Add a task</a>
</div>
</body>
</html>
This is my add.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<title>Task Page</title>
</head>
<body>
<form:form method="POST" action="/task-add" modelAttribute="task">
<div>
<form:label path="title">Title</form:label>
<form:input path="title" />
</div>
<div>
<form:label path="desc">Description</form:label>
<form:input path="desc" />
</div>
<div>
<input type="submit" value="Add">
</div>
</form:form>
</body>
</html>
In term of the session-scoped attribute, it's working as I expect. The TaskService.retrieveTasks()
function is only called the 1st time I access the view.jsp
. Subsequently, the same list of task is pulled from the Session.
The problem is when I try to add two new Task
on the add.jsp
page, I saw the following lines in the console.
CALLING TASK SERVICE TO GET LIST OF TASKS
GETTING TASK LIST FOR THE FIRST TIME
ADDING NEW TASK: 0
DONE ADDING NEW TASK: 2
ADDING NEW TASK: 2
DONE ADDING NEW TASK: 4
The 1st two lines were printed when I accessed the view.jsp
for the 1st time, which is right. However, I have no idea what's happening between the ADDING NEW TASK
and DONE ADDING NEW TASK
lines. I'd be very grateful if someone could explain to me why the line below is adding a duplicate in my list of Task
taskList.add(taskService.addTask(newTask.getTitle(), newTask.getDesc(), new Date()));
I also tried to remove the taskList.add()
portion and only made a service call to taskService.addTask()
. In this case, there's no duplicate and my taskList
is updated with one new record. However, I don't understand how the taskService
could indirectly modify my taskList
when there's no injection in the TaskService
class.
Did I miss something?
java spring spring-mvc spring-boot session
1
You reference the same list twice, and thus add theTask
twice to the same list. The dangers of caching... Instead of trying to sync the cache just add it once in the service and just refresh the cached list. Instead of trying to manually keep them up-to-date...
– M. Deinum
Nov 20 '18 at 10:00
@M.Deinum Thank you for pointing out my mistake. I tried to implement a simple example to learn Spring. I thought I was misunderstanding Spring in some way and I never realized I made such a basic Java mistake.
– Mr.J4mes
Nov 20 '18 at 11:47
add a comment |
To pick up Spring, I'm playing around with very simple pages to understand the annotations and the behaviors of Spring in general. To be precise, I created a page to show a list of Task
and another page to add a new Task
. I used @SessionAttibutes
to save the list of Task in the session instead of calling a service to retrieve a full list of Task
everytime I access the task list page.
This is my TaskService
@Service
public class TaskService {
private List<Task> taskCache = new ArrayList<Task>();
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return taskCache;
}
public Task addTask(String title, String desc, Date targetDate) {
Task newTask = new Task(title, desc, targetDate);
taskCache.add(newTask);
return newTask;
}
}
This is my TaskController
@Controller
@SessionAttributes("taskList")
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/task-view")
public String showTaskList() {
return "task/view";
}
@GetMapping("/task-add")
public String showAddTaskForm(@ModelAttribute("task") Task newTask) {
return "task/add";
}
@PostMapping("/task-add")
public String addTask(ModelMap model, @ModelAttribute("task") Task newTask, @ModelAttribute("taskList") List<Task> taskList) {
System.out.println("ADDING NEW TASK: " + taskList.size());
taskList.add(taskService.addTask(newTask.getTitle(), newTask.getDesc(), new Date()));
System.out.println("DONE ADDING NEW TASK: " + taskList.size());
return "redirect:/task-view";
}
@ModelAttribute("taskList")
public List<Task> taskList() {
System.out.println("CALLING TASK SERVICE TO GET LIST OF TASKS");
return taskService.retrieveTasks();
}
}
This is my view.jsp
<html>
<head>
<title>Task Page</title>
</head>
<body>
This is your task list:
${taskList}
<div>
<a href="task-add">Add a task</a>
</div>
</body>
</html>
This is my add.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<title>Task Page</title>
</head>
<body>
<form:form method="POST" action="/task-add" modelAttribute="task">
<div>
<form:label path="title">Title</form:label>
<form:input path="title" />
</div>
<div>
<form:label path="desc">Description</form:label>
<form:input path="desc" />
</div>
<div>
<input type="submit" value="Add">
</div>
</form:form>
</body>
</html>
In term of the session-scoped attribute, it's working as I expect. The TaskService.retrieveTasks()
function is only called the 1st time I access the view.jsp
. Subsequently, the same list of task is pulled from the Session.
The problem is when I try to add two new Task
on the add.jsp
page, I saw the following lines in the console.
CALLING TASK SERVICE TO GET LIST OF TASKS
GETTING TASK LIST FOR THE FIRST TIME
ADDING NEW TASK: 0
DONE ADDING NEW TASK: 2
ADDING NEW TASK: 2
DONE ADDING NEW TASK: 4
The 1st two lines were printed when I accessed the view.jsp
for the 1st time, which is right. However, I have no idea what's happening between the ADDING NEW TASK
and DONE ADDING NEW TASK
lines. I'd be very grateful if someone could explain to me why the line below is adding a duplicate in my list of Task
taskList.add(taskService.addTask(newTask.getTitle(), newTask.getDesc(), new Date()));
I also tried to remove the taskList.add()
portion and only made a service call to taskService.addTask()
. In this case, there's no duplicate and my taskList
is updated with one new record. However, I don't understand how the taskService
could indirectly modify my taskList
when there's no injection in the TaskService
class.
Did I miss something?
java spring spring-mvc spring-boot session
To pick up Spring, I'm playing around with very simple pages to understand the annotations and the behaviors of Spring in general. To be precise, I created a page to show a list of Task
and another page to add a new Task
. I used @SessionAttibutes
to save the list of Task in the session instead of calling a service to retrieve a full list of Task
everytime I access the task list page.
This is my TaskService
@Service
public class TaskService {
private List<Task> taskCache = new ArrayList<Task>();
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return taskCache;
}
public Task addTask(String title, String desc, Date targetDate) {
Task newTask = new Task(title, desc, targetDate);
taskCache.add(newTask);
return newTask;
}
}
This is my TaskController
@Controller
@SessionAttributes("taskList")
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/task-view")
public String showTaskList() {
return "task/view";
}
@GetMapping("/task-add")
public String showAddTaskForm(@ModelAttribute("task") Task newTask) {
return "task/add";
}
@PostMapping("/task-add")
public String addTask(ModelMap model, @ModelAttribute("task") Task newTask, @ModelAttribute("taskList") List<Task> taskList) {
System.out.println("ADDING NEW TASK: " + taskList.size());
taskList.add(taskService.addTask(newTask.getTitle(), newTask.getDesc(), new Date()));
System.out.println("DONE ADDING NEW TASK: " + taskList.size());
return "redirect:/task-view";
}
@ModelAttribute("taskList")
public List<Task> taskList() {
System.out.println("CALLING TASK SERVICE TO GET LIST OF TASKS");
return taskService.retrieveTasks();
}
}
This is my view.jsp
<html>
<head>
<title>Task Page</title>
</head>
<body>
This is your task list:
${taskList}
<div>
<a href="task-add">Add a task</a>
</div>
</body>
</html>
This is my add.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<title>Task Page</title>
</head>
<body>
<form:form method="POST" action="/task-add" modelAttribute="task">
<div>
<form:label path="title">Title</form:label>
<form:input path="title" />
</div>
<div>
<form:label path="desc">Description</form:label>
<form:input path="desc" />
</div>
<div>
<input type="submit" value="Add">
</div>
</form:form>
</body>
</html>
In term of the session-scoped attribute, it's working as I expect. The TaskService.retrieveTasks()
function is only called the 1st time I access the view.jsp
. Subsequently, the same list of task is pulled from the Session.
The problem is when I try to add two new Task
on the add.jsp
page, I saw the following lines in the console.
CALLING TASK SERVICE TO GET LIST OF TASKS
GETTING TASK LIST FOR THE FIRST TIME
ADDING NEW TASK: 0
DONE ADDING NEW TASK: 2
ADDING NEW TASK: 2
DONE ADDING NEW TASK: 4
The 1st two lines were printed when I accessed the view.jsp
for the 1st time, which is right. However, I have no idea what's happening between the ADDING NEW TASK
and DONE ADDING NEW TASK
lines. I'd be very grateful if someone could explain to me why the line below is adding a duplicate in my list of Task
taskList.add(taskService.addTask(newTask.getTitle(), newTask.getDesc(), new Date()));
I also tried to remove the taskList.add()
portion and only made a service call to taskService.addTask()
. In this case, there's no duplicate and my taskList
is updated with one new record. However, I don't understand how the taskService
could indirectly modify my taskList
when there's no injection in the TaskService
class.
Did I miss something?
java spring spring-mvc spring-boot session
java spring spring-mvc spring-boot session
edited Nov 20 '18 at 7:23
Mr.J4mes
asked Nov 20 '18 at 7:13
Mr.J4mesMr.J4mes
6,69563875
6,69563875
1
You reference the same list twice, and thus add theTask
twice to the same list. The dangers of caching... Instead of trying to sync the cache just add it once in the service and just refresh the cached list. Instead of trying to manually keep them up-to-date...
– M. Deinum
Nov 20 '18 at 10:00
@M.Deinum Thank you for pointing out my mistake. I tried to implement a simple example to learn Spring. I thought I was misunderstanding Spring in some way and I never realized I made such a basic Java mistake.
– Mr.J4mes
Nov 20 '18 at 11:47
add a comment |
1
You reference the same list twice, and thus add theTask
twice to the same list. The dangers of caching... Instead of trying to sync the cache just add it once in the service and just refresh the cached list. Instead of trying to manually keep them up-to-date...
– M. Deinum
Nov 20 '18 at 10:00
@M.Deinum Thank you for pointing out my mistake. I tried to implement a simple example to learn Spring. I thought I was misunderstanding Spring in some way and I never realized I made such a basic Java mistake.
– Mr.J4mes
Nov 20 '18 at 11:47
1
1
You reference the same list twice, and thus add the
Task
twice to the same list. The dangers of caching... Instead of trying to sync the cache just add it once in the service and just refresh the cached list. Instead of trying to manually keep them up-to-date...– M. Deinum
Nov 20 '18 at 10:00
You reference the same list twice, and thus add the
Task
twice to the same list. The dangers of caching... Instead of trying to sync the cache just add it once in the service and just refresh the cached list. Instead of trying to manually keep them up-to-date...– M. Deinum
Nov 20 '18 at 10:00
@M.Deinum Thank you for pointing out my mistake. I tried to implement a simple example to learn Spring. I thought I was misunderstanding Spring in some way and I never realized I made such a basic Java mistake.
– Mr.J4mes
Nov 20 '18 at 11:47
@M.Deinum Thank you for pointing out my mistake. I tried to implement a simple example to learn Spring. I thought I was misunderstanding Spring in some way and I never realized I made such a basic Java mistake.
– Mr.J4mes
Nov 20 '18 at 11:47
add a comment |
2 Answers
2
active
oldest
votes
The problem is in the method retrieveTasks
:
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return taskCache;
}
This method returns a reference to the taskCache
object. Everybody with access to this reference can modify this mutable List. E.g. in PHP, if you returned an array, than by default, you would receive a copy of the array. Not in Java.
You should modify the method like this:
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return new ArrayList<>(taskCache); // create copy of taskCache
}
This is in fact, what a real service would be doing. Data would be stored in a database, but you would not return a direct reference to that data. You would always pull current data from DB and materialize it in a brand new List.
Damn. Thank you. I spent way too much time thinking about Spring that I didn't realize such a basic mistake in Java!
– Mr.J4mes
Nov 20 '18 at 11:34
add a comment |
@ModelAttribute("taskList")
public List<Task> taskList() {
System.out.println("CALLING TASK SERVICE TO GET LIST OF TASKS");
return taskService.retrieveTasks();
}
I think that's what you're missing. taskList() method returns taskCache list and that's the list taskService modifies. So taksList and taskCache are the same object.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53387965%2fspring-adding-one-record-to-a-list-suddenly-creates-a-duplicate%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The problem is in the method retrieveTasks
:
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return taskCache;
}
This method returns a reference to the taskCache
object. Everybody with access to this reference can modify this mutable List. E.g. in PHP, if you returned an array, than by default, you would receive a copy of the array. Not in Java.
You should modify the method like this:
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return new ArrayList<>(taskCache); // create copy of taskCache
}
This is in fact, what a real service would be doing. Data would be stored in a database, but you would not return a direct reference to that data. You would always pull current data from DB and materialize it in a brand new List.
Damn. Thank you. I spent way too much time thinking about Spring that I didn't realize such a basic mistake in Java!
– Mr.J4mes
Nov 20 '18 at 11:34
add a comment |
The problem is in the method retrieveTasks
:
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return taskCache;
}
This method returns a reference to the taskCache
object. Everybody with access to this reference can modify this mutable List. E.g. in PHP, if you returned an array, than by default, you would receive a copy of the array. Not in Java.
You should modify the method like this:
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return new ArrayList<>(taskCache); // create copy of taskCache
}
This is in fact, what a real service would be doing. Data would be stored in a database, but you would not return a direct reference to that data. You would always pull current data from DB and materialize it in a brand new List.
Damn. Thank you. I spent way too much time thinking about Spring that I didn't realize such a basic mistake in Java!
– Mr.J4mes
Nov 20 '18 at 11:34
add a comment |
The problem is in the method retrieveTasks
:
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return taskCache;
}
This method returns a reference to the taskCache
object. Everybody with access to this reference can modify this mutable List. E.g. in PHP, if you returned an array, than by default, you would receive a copy of the array. Not in Java.
You should modify the method like this:
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return new ArrayList<>(taskCache); // create copy of taskCache
}
This is in fact, what a real service would be doing. Data would be stored in a database, but you would not return a direct reference to that data. You would always pull current data from DB and materialize it in a brand new List.
The problem is in the method retrieveTasks
:
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return taskCache;
}
This method returns a reference to the taskCache
object. Everybody with access to this reference can modify this mutable List. E.g. in PHP, if you returned an array, than by default, you would receive a copy of the array. Not in Java.
You should modify the method like this:
public List<Task> retrieveTasks() {
System.out.println("GETTING TASK LIST FOR THE FIRST TIME");
return new ArrayList<>(taskCache); // create copy of taskCache
}
This is in fact, what a real service would be doing. Data would be stored in a database, but you would not return a direct reference to that data. You would always pull current data from DB and materialize it in a brand new List.
answered Nov 20 '18 at 9:12
ygorygor
1,087615
1,087615
Damn. Thank you. I spent way too much time thinking about Spring that I didn't realize such a basic mistake in Java!
– Mr.J4mes
Nov 20 '18 at 11:34
add a comment |
Damn. Thank you. I spent way too much time thinking about Spring that I didn't realize such a basic mistake in Java!
– Mr.J4mes
Nov 20 '18 at 11:34
Damn. Thank you. I spent way too much time thinking about Spring that I didn't realize such a basic mistake in Java!
– Mr.J4mes
Nov 20 '18 at 11:34
Damn. Thank you. I spent way too much time thinking about Spring that I didn't realize such a basic mistake in Java!
– Mr.J4mes
Nov 20 '18 at 11:34
add a comment |
@ModelAttribute("taskList")
public List<Task> taskList() {
System.out.println("CALLING TASK SERVICE TO GET LIST OF TASKS");
return taskService.retrieveTasks();
}
I think that's what you're missing. taskList() method returns taskCache list and that's the list taskService modifies. So taksList and taskCache are the same object.
add a comment |
@ModelAttribute("taskList")
public List<Task> taskList() {
System.out.println("CALLING TASK SERVICE TO GET LIST OF TASKS");
return taskService.retrieveTasks();
}
I think that's what you're missing. taskList() method returns taskCache list and that's the list taskService modifies. So taksList and taskCache are the same object.
add a comment |
@ModelAttribute("taskList")
public List<Task> taskList() {
System.out.println("CALLING TASK SERVICE TO GET LIST OF TASKS");
return taskService.retrieveTasks();
}
I think that's what you're missing. taskList() method returns taskCache list and that's the list taskService modifies. So taksList and taskCache are the same object.
@ModelAttribute("taskList")
public List<Task> taskList() {
System.out.println("CALLING TASK SERVICE TO GET LIST OF TASKS");
return taskService.retrieveTasks();
}
I think that's what you're missing. taskList() method returns taskCache list and that's the list taskService modifies. So taksList and taskCache are the same object.
edited Nov 20 '18 at 9:06
answered Nov 20 '18 at 8:51
Ilya SazonovIlya Sazonov
20624
20624
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53387965%2fspring-adding-one-record-to-a-list-suddenly-creates-a-duplicate%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
You reference the same list twice, and thus add the
Task
twice to the same list. The dangers of caching... Instead of trying to sync the cache just add it once in the service and just refresh the cached list. Instead of trying to manually keep them up-to-date...– M. Deinum
Nov 20 '18 at 10:00
@M.Deinum Thank you for pointing out my mistake. I tried to implement a simple example to learn Spring. I thought I was misunderstanding Spring in some way and I never realized I made such a basic Java mistake.
– Mr.J4mes
Nov 20 '18 at 11:47