My Thymeleaf cant compile, i can't understand what's wrong. I need to create checkbox and make checked only roles, which user contains.
I reŃeive this execption: Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "user.getRoles().contains(${role})" (template: "editUser" - line 19, col 54)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.attoparser.MarkupParser.parse(MarkupParser.java:257) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230) ~[thymeleaf-3.0.15.RELEASE.jar:3.0.15.RELEASE]
... 89 common frames omitted
Role(entity):
#Entity
#Table(name = "sweater_roles")
public class Role implements GrantedAuthority {
public static List<Role> allRoles = Arrays.asList(new Role("USER"), new Role("ADMIN"));
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
public Role(String name) {
this.name = name;
}
public Role() {
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Role)) return false;
Role role = (Role) o;
return getName().equals(role.getName());
}
#Override
public int hashCode() {
return Objects.hash(getName());
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String getAuthority() {
return getName();
}
}
User(entity):
#Entity
#Table(name = "sweater_user")
public class User implements UserDetails{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private boolean active;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "sweater_user_role",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "role_id", referencedColumnName = "id")
)
private Collection<Role> roles;
public User(String username, String password, boolean active, Collection<Role> roles) {
this.username = username;
this.password = password;
this.active = active;
this.roles = roles;
}
public User() {
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return isActive();
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return getRoles();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public Collection<Role> getRoles() {
return roles;
}
public void setRoles(Collection<Role> roles) {
this.roles = roles;
}
}
Controller:
#GetMapping("{user}")
public String editUser(#PathVariable User user, Model model){
model.addAttribute("user", user);
model.addAttribute("roles", Role.allRoles);
return "editUser";
}
HTML file:
Roles:
<th:block th:each="role : ${roles}">
<div>
<label th:for="${role}" th:text="${role}"></label>
<input type="checkbox" th:name="${role}" th:checked="${user.getRoles().contains(${role})}">
</div>
</th:block>
I'm trying to create a html "Edit/New" page to edit or add new a publisher. One of the details would be an ArrayList of subPublishers. Although the ArrayList might be empty if the publisher has no subPublishers or if i add new publisher.
My issue is with the input fields. I'm attempting to show the ArrayList as follows...
<form id="publisherForm" th:object="${publisherForm}" th:action="#{/publishers/publishers-edit/}" method="post" class="form-horizontal">
<input type="hidden" th:field="*{id}" />
<div class="row">
<div class="col-sm-6 b-r">
<div class="form-group">
<label class="col-sm-3 control-label">Publisher name: </label>
<div class="col-sm-9">
<input th:field="*{publisherName}" type="text" class="form-control" th:maxlength="45"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Description: </label>
<div class="col-sm-9">
<input th:field="*{description}" type="text" class="form-control" th:maxlength="200"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Enabled: </label>
<div class="col-sm-9">
<input th:field="*{status}" value="ENABLED" type="checkbox"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Website URL: </label>
<div class="col-sm-9">
<input th:field="*{websiteURL}" type="text" class="form-control" th:maxlength="50"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Subpublishers: </label>
<div class="col-sm-9">
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<th>
<button class="btn btn-white" type="submit" name="addRow">+</button>
</th>
</thead>
<tbody>
<tr th:each="subPublisher,stat : *{subPublishers}">
<td>
<input type="text" class="form-control" th:field="*{subPublishers[__${stat.index}__].name}" />
</td>
<td>
<button class="btn btn-white" type="submit" name="removeRow" th:value="${stat.index}">-</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3">
<button class="btn btn-primary" type="submit">Save</button>
<a class="btn btn-white" th:href="#{/publishers}">Cancel</a>
</div>
</div>
</div>
</div>
</form>
Controller
#MenuController(value = "/publisher", item = Item.Publishers)
public class PublisherController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
public PublisherController(PublisherService publisherService, PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
#GetMapping
public String newPublisher( Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
publisher.setSubPublishers(new ArrayList<SubPublisherResource>());
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "publishers/publishers-edit";
}
#PostMapping
public String createPublisher(#ModelAttribute("publisherForm") #Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(0, resource);
}
#GetMapping("/{publisherId}")
public String editPublisher(#PathVariable int publisherId, Model model) {
Publisher publisher = publisherService.getPublisher(publisherId);
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream()
.map(s -> subPublisherConverter.convert(s))
.collect(Collectors.toList())
);
return showPage(res, model);
}
#PostMapping("/{publisherId}")
public String updatePublisher(#PathVariable int publisherId, #ModelAttribute("publisherForm") #Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(publisherId, resource);
}
protected String savePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = populatePublisher(publisherId, resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if (publisherId == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = null;
if (publisherId == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(publisherId);
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource){
if(resource.getSubPublishers() != null){
return resource.getSubPublishers().stream()
.map(s -> {
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
})
.collect(Collectors.toList());
}
return Collections.emptyList();
}
#PostMapping(params={"addRow"})
public String addRow(final PublisherResource publisher, final BindingResult bindingResult, Model model) {
publisher.getSubPublishers().add(new SubPublisherResource());
return showPage(publisher, model);
}
#PostMapping(params={"removeRow"})
public String removeRow(final PublisherResource publisher, final BindingResult bindingResult,
final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
PublisherResource
public class PublisherResource {
private int id;
private String publisherName;
private String description;
private boolean status;
private String websiteURL;
private List<SubPublisherResource> subPublishers = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public List<SubPublisherResource> getSubPublishers() {
return subPublishers;
}
public void setSubPublishers(List<SubPublisherResource> subPublishers) {
this.subPublishers = subPublishers;
}
}
I use exampel from thymeleaf documentation http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#dynamic-fields
The problem is that when the ArrayList is empty, the input fields do not show on the page! Also when edit publisher that have subpublishers, if i remove all of them i lose input fields and I can't add any other subpublishers. Which pretty much makes it impossible to add an subpublishers.
How is this handled with Thymeleaf?
Update Controller
#MenuController(value = "/publisher", item = Item.Publishers)
public class PublisherController {
private PublisherResource publisherResource;
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
public PublisherController(PublisherResource publisherResource, PublisherService publisherService,
PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherResource = publisherResource;
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
#GetMapping
public String newPublisher( Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
publisher.setSubPublishers(new ArrayList<SubPublisherResource>());
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "publishers/publishers-edit";
}
#PostMapping
public String createPublisher(#ModelAttribute("publisherForm") #Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(0, resource);
}
#GetMapping
public String editPublisher(Model model) {
Publisher publisher = publisherService.getPublisher(publisherResource.getId());
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream()
.map(s -> subPublisherConverter.convert(s))
.collect(Collectors.toList())
);
return showPage(res, model);
}
#PostMapping
public String updatePublisher( #ModelAttribute("publisherForm") #Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(publisherResource.getId(), resource);
}
protected String savePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = populatePublisher(publisherId, resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if (publisherId == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = null;
if (publisherId == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(publisherId);
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource){
if(resource.getSubPublishers() != null){
return resource.getSubPublishers().stream()
.map(s -> {
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
})
.collect(Collectors.toList());
}
return Collections.emptyList();
}
#PostMapping(params={"addRow"})
public String addRow(final PublisherResource publisher, final BindingResult bindingResult, Model model) {
publisher.getSubPublishers().add(new SubPublisherResource());
return showPage(publisher, model);
}
#PostMapping(params={"removeRow"})
public String removeRow(final PublisherResource publisher, final BindingResult bindingResult,
final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
Update 2 - all code:
Entities Publisher and SubPublisher:
#Entity
#Table(name = "publisher")
public class Publisher {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name")
private String publisherName;
#Column(name = "description")
private String description;
#Column(name = "status")
private boolean status;
#Column(name = "website_url")
private String websiteURL;
#Column(name = "time_added")
private Date timeAdded;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public Date getTimeAdded() {
return timeAdded;
}
public void setTimeAdded(Date timeAdded) {
this.timeAdded = timeAdded;
}
}
#Entity
#Table(name = "sub_publisher")
public class SubPublisher {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "publisher_id")
private Publisher publisher;
#Column(name = "name")
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Repositories
public interface PublisherRepository extends JpaDataTableRepository<Publisher, Integer> {
public Publisher findById(int id);
}
public interface SubPublisherRepository extends JpaRepository<SubPublisher, Integer> {
List<SubPublisher> findByPublisher(Publisher publisher);
void deleteByPublisher(Publisher publisher);
}
PublisherResource
public class PublisherResource {
private int id;
private String publisherName;
private String description;
private boolean status;
private String websiteURL;
private List<SubPublisherResource> subPublishers = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public List<SubPublisherResource> getSubPublishers() {
return subPublishers;
}
public void setSubPublishers(List<SubPublisherResource> subPublishers) {
this.subPublishers = subPublishers;
}
}
SubPublisherResource
public class SubPublisherResource {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
PublisherController
#Controller
#RequestMapping("/publisher")
public class PublisherController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
#Autowired
public PublisherController(PublisherService publisherService, PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
#GetMapping
public String newPublisher(Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "/publishers/publishers-edit";
}
#PostMapping
public String createPublisher(#ModelAttribute("publisherForm") #Validated PublisherResource resource, BindingResult result, Model model) {
if(result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(resource);
}
#GetMapping("/{id}")
public String editPublisher(#PathVariable("id") Integer id, Model model) {
Publisher publisher = publisherService.getPublisher(id);
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream().map(s->subPublisherConverter.convert(s)).collect(Collectors.toList()));
return showPage(res, model);
}
protected String savePublisher(PublisherResource resource) {
Publisher publisher = populatePublisher(resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if(resource.getId() == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(PublisherResource resource) {
Publisher publisher;
if(resource.getId() == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(resource.getId());
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource) {
if(resource.getSubPublishers() != null) {
return resource.getSubPublishers().stream().map(s->{
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
}).collect(Collectors.toList());
}
return Collections.emptyList();
}
#PostMapping(params = { "addRow" })
public String addRow(final PublisherResource publisher, Model model) {
publisher.getSubPublishers().add(new SubPublisher());
return showPage(publisher, model);
}
#PostMapping(params = { "removeRow" })
public String removeRow(final PublisherResource publisher, final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
PublishersController
#MenuController(value = "/publishers", item = Item.Publishers)
public class PublishersController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
public PublishersController(PublisherService publisherService, PublisherConverter publisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
}
#GetMapping
public String showPage() {
return "publishers/publishers";
}
#PostMapping("/data")
public #ResponseBody DataTableResponse<PublisherResource> getPublishers(#RequestBody DataTableRequest request) {
return publisherConverter.convertResponse(publisherService.getPublishers(request));
}
#DeleteMapping("/{publisherIds}")
#ResponseStatus(HttpStatus.NO_CONTENT)
public void deletePublishers(#PathVariable Integer[] publisherIds) {
for (Integer publisherId: publisherIds) {
publisherService.deletePublisher(publisherId);
}
}
#PutMapping("/{publisherIds}/disable")
#ResponseStatus(HttpStatus.ACCEPTED)
public void disablePublishers(#PathVariable Integer[] publisherIds) {
changeStatus(publisherIds);
}
#PutMapping("/{publisherIds}/enable")
#ResponseStatus(HttpStatus.ACCEPTED)
public void enablePublishers(#PathVariable Integer[] publisherIds) {
changeStatus(publisherIds);
}
protected void changeStatus(Integer[] publisherIds) {
for (Integer publisherId: publisherIds) {
publisherService.updateStatus(publisherId);
}
}
}
PublisherConverter
#Component
public class PublisherConverter implements ResourceConverter<Publisher, PublisherResource> {
public PublisherResource convert(Publisher publisher) {
PublisherResource resource = new PublisherResource();
resource.setId(publisher.getId());
resource.setPublisherName(publisher.getPublisherName());
resource.setDescription(publisher.getDescription());
resource.setStatus(publisher.isStatus());
resource.setWebsiteURL(publisher.getWebsiteURL());
return resource;
}
}
PublisherService
#Service
public class PublisherService {
private PublisherRepository publisherRepository;
private SubPublisherRepository subPublisherRepository;
public PublisherService(PublisherRepository publisherRepository, SubPublisherRepository subPublisherRepository) {
this.publisherRepository = publisherRepository;
this.subPublisherRepository = subPublisherRepository;
}
public DataTableResponse<Publisher> getPublishers(DataTableRequest request) {
return publisherRepository.findAll(request);
}
#Transactional
public Publisher getPublisher(int publisherId) {
Publisher publisher = publisherRepository.findById(publisherId);
if(publisher != null){
List<SubPublisher> subPublishers = subPublisherRepository.findByPublisher(publisher);
//populateSubPublishers(subPublishers);
subPublishers.stream().forEach(s -> {
if(s.getId() == 0){
s.setPublisher(publisher);
subPublisherRepository.save(s);
}
});
}
if(publisher == null) {
throw new NotFoundException("Publisher " + publisherId + " not found.");
}
return publisher;
}
private void populateSubPublishers(List<SubPublisher> subPublishers) {
for(SubPublisher subPublisher : subPublishers){
subPublishers.add(subPublisher);
System.out.println(subPublisher.getName());
}
}
#Transactional
public Publisher createPublisher(Publisher publisher, List<SubPublisher> subPublishers) {
publisher = publisherRepository.save(publisher);
createSubPublisher(publisher, subPublishers);
return publisher;
}
private void createSubPublisher(Publisher publisher, List<SubPublisher> subPublishers) {
populateSubPublishers(subPublishers);
for(SubPublisher subPublisher : subPublishers){
subPublisher.setPublisher(publisher);
subPublisher.setName(subPublisher.getName());
}
}
#Transactional
public Publisher updatePublisher(Publisher publisher, List<SubPublisher> subPublishers) {
publisher = publisherRepository.save(publisher);
createSubPublishers(publisher, subPublishers);
return publisher;
}
private void createSubPublishers(Publisher publisher, List<SubPublisher> subPublishers) {
subPublisherRepository.deleteByPublisher(publisher);
for (SubPublisher sp : subPublishers) {
sp.setPublisher(publisher);
sp = subPublisherRepository.save(sp);
}
}
#Transactional
public void updateStatus(int publisherId) {
Publisher publisher = publisherRepository.findOne(publisherId);
if(publisher != null && publisher.isStatus() != false){
publisher.setStatus(false);
publisherRepository.save(publisher);
}
else if(publisher != null && publisher.isStatus() != true ){
publisher.setStatus(true);
publisherRepository.save(publisher);
}
}
#Transactional
public void deletePublisher(int publisherId) {
Publisher publisher = publisherRepository.findOne(publisherId);
if (publisher != null) {
publisherRepository.delete(publisher);
}
}
public List<SubPublisher> getSubPublishers(Publisher publisher){
return subPublisherRepository.findByPublisher(publisher);
}
}
SubPublisherConverter
#Component
public class SubPublisherConverter implements ResourceConverter<SubPublisher, SubPublisherResource> {
#Override
public SubPublisherResource convert(SubPublisher subPublisher) {
SubPublisherResource resource = new SubPublisherResource();
resource.setName(subPublisher.getName());
return resource;
}
}
Error
java.util.ConcurrentModificationException: null
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at publishers.PublisherService.populateSubPublishers(PublisherService.java:58)
at publishers.PublisherService.createSubPublisher(PublisherService.java:74)
at publishers.PublisherService.createPublisher(PublisherService.java:68)
So here is the example. Ofc you need to replace the mapping for the controller (/test/test) to /publishers/publishers-edit. Controller:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
#Controller
#RequestMapping("/test/test")
public class PublisherController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
#Autowired
public PublisherController(PublisherService publisherService, PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
#GetMapping
public String newPublisher(Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "test/test";
}
#PostMapping
public String createPublisher(#ModelAttribute("publisherForm") #Validated PublisherResource resource, BindingResult result, Model model) {
if(result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(resource);
}
#GetMapping("/{id}")
public String editPublisher(#PathVariable("id") Integer id, Model model) {
Publisher publisher = publisherService.getPublisher(id);
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream().map(s->subPublisherConverter.convert(s)).collect(Collectors.toList()));
return showPage(res, model);
}
protected String savePublisher(PublisherResource resource) {
Publisher publisher = populatePublisher(resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if(resource.getId() == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(PublisherResource resource) {
Publisher publisher;
if(resource.getId() == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(resource.getId());
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource) {
if(resource.getSubPublishers() != null) {
return resource.getSubPublishers().stream().map(s->{
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
}).collect(Collectors.toList());
}
return Collections.emptyList();
}
#PostMapping(params = { "addRow" })
public String addRow(#ModelAttribute("publisherForm") final PublisherResource publisher, Model model) {
publisher.getSubPublishers().add(new SubPublisher());
return showPage(publisher, model);
}
#PostMapping(params = { "removeRow" })
public String removeRow(#ModelAttribute("publisherForm") final PublisherResource publisher, final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
Update
I cleaned up your PublisherService and splitted it into PublisherService and SubPublisherService. Those Services are prob. optional but i prefer to have another layer between the repository and my programm most of the time.
I also cleaned up the PublisherController. savePublisher changed a lot. It is documented tho.
The Publisher now also has a List containing all SubPublishers for the Publisher. Prev. you were fetching this via code. However JPA can do this for you.
PublisherController:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
#Controller
#RequestMapping("/test/test")
public class PublisherController {
private PublisherService publisherService;
private SubPublisherService subPublisherService;
#Autowired
public PublisherController(PublisherService publisherService, SubPublisherService subPublisherService) {
this.publisherService = publisherService;
this.subPublisherService = subPublisherService;
}
private ModelAndView showPage(PublisherResource publisher) {
final ModelAndView modelAndView = new ModelAndView("test/test");
modelAndView.addObject("publisherForm", publisher);
return modelAndView;
}
#GetMapping
public ModelAndView createPublisher() {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
return showPage(publisher);
}
#GetMapping("/{id}")
public ModelAndView editPublisher(#PathVariable("id") Integer id) {
Publisher publisher = publisherService.getPublisher(id);
return showPage(PublisherConverter.convert(publisher));
}
#PostMapping
public ModelAndView savePublisher(#ModelAttribute("publisherForm") #Validated PublisherResource resource, BindingResult result) {
if(result.hasErrors()) {
return showPage(resource);
}
return savePublisher(resource);
}
private ModelAndView savePublisher(PublisherResource resource) {
// create the publisher
Publisher publisher;
if(resource.getId() == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
publisher = publisherService.save(publisher);
} else {
publisher = publisherService.getPublisher(resource.getId());
}
/* -- this will update the SubPublishers -- */
final List<SubPublisher> toDelete = publisher.getSubPublishers();
final List<SubPublisher> toSave = new ArrayList<>();
final Publisher forLambda = publisher;
// first we will iterate over all the SubPublishers that where specified by the user (in the form)
resource.getSubPublishers().forEach(name->{
// we will then try to find any existing SubPublisher for the given name and publisher (to avoid duplicated database entries)
final SubPublisher subPublisher = subPublisherService.getOrCreateSubPublisher(forLambda, name);
// we will also save the SubPublisher reference for later
toSave.add(subPublisher);
// and then we will remove the SubPublisher that we just found from the List of SubPublishers from the original Publisher (that was stored in the db)
toDelete.removeIf(s->subPublisher.getId() == s.getId());
});
// effectively it will leave us with a list (toDelete) that will include all SubPublishers that have to be deleted
for(SubPublisher subPublisher : toDelete) {
// and this is what we will to here
subPublisherService.delete(subPublisher);
}
// after we cleaned up all unused references
publisher.getSubPublishers().clear();
// update the subPublisher list to contain all SubPublishers that where specified by the user input (the parsed ones)
publisher.getSubPublishers().addAll(toSave);
/* -- end -- */
// update all remaining fields
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
publisherService.save(publisher);
return new ModelAndView("redirect:/test/list");
}
#PostMapping(params = { "addRow" })
public ModelAndView addRow(#ModelAttribute("publisherForm") final PublisherResource publisher) {
publisher.getSubPublishers().add("");
return showPage(publisher);
}
#PostMapping(params = { "removeRow" })
public ModelAndView removeRow(#ModelAttribute("publisherForm") final PublisherResource publisher, final HttpServletRequest req) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher);
}
}
Publisher:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
#Entity
#Table
public class Publisher {
private int id;
private String publisherName;
private String description;
private boolean status;
private String websiteURL;
private Date timeAdded;
private List<SubPublisher> subPublishers = new ArrayList<>();
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
#Column
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Column
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
#Column
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
#Column
public Date getTimeAdded() {
return timeAdded;
}
public void setTimeAdded(Date timeAdded) {
this.timeAdded = timeAdded;
}
#OneToMany(mappedBy = "publisher")
public List<SubPublisher> getSubPublishers() {
return subPublishers;
}
public void setSubPublishers(List<SubPublisher> subPublishers) {
this.subPublishers = subPublishers;
}
#Override
public String toString() {
return "Publisher{" + "id=" + id + ", publisherName='" + publisherName + '\'' + ", description='" + description + '\'' + ", status=" + status + ", websiteURL='" + websiteURL + '\'' + ", timeAdded=" + timeAdded + ", subPublishers=" + subPublishers + '}';
}
}
PublisherResource:
import java.util.ArrayList;
import java.util.List;
public class PublisherResource {
private int id;
private String publisherName;
private String description;
private boolean status;
private String websiteURL;
private List<String> subPublishers = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public List<String> getSubPublishers() {
return subPublishers;
}
public void setSubPublishers(List<String> subPublishers) {
this.subPublishers = subPublishers;
}
}
PublisherService:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class PublisherService {
private PublisherRepository publisherRepository;
#Autowired
public void setPublisherRepository(PublisherRepository publisherRepository) {
this.publisherRepository = publisherRepository;
}
public Publisher save(Publisher toSave) {
return publisherRepository.save(toSave);
}
public void delete(Publisher toDelete) {
publisherRepository.delete(toDelete);
}
public Publisher getPublisher(Integer id) {
return publisherRepository.findOne(id);
}
public Iterable<Publisher> getAll() {
return publisherRepository.findAll();
}
}
PublisherRepository:
import org.springframework.data.repository.CrudRepository;
public interface PublisherRepository extends CrudRepository<Publisher, Integer> {}
PublisherConverter:
import java.util.stream.Collectors;
public class PublisherConverter {
public static PublisherResource convert(Publisher publisher) {
PublisherResource resource = new PublisherResource();
resource.setId(publisher.getId());
resource.setPublisherName(publisher.getPublisherName());
resource.setDescription(publisher.getDescription());
resource.setStatus(publisher.isStatus());
resource.setWebsiteURL(publisher.getWebsiteURL());
resource.getSubPublishers().addAll(publisher.getSubPublishers().stream().map(SubPublisher::getName).collect(Collectors.toList()));
return resource;
}
}
SubPublisher:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table
public class SubPublisher {
private int id;
private Publisher publisher;
private String name;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "publisherId")
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
#Column
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
SubPublisherRepository:
import org.springframework.data.repository.CrudRepository;
public interface SubPublisherRepository extends CrudRepository<SubPublisher, Integer> {
SubPublisher findByPublisherAndAndName(Publisher publisher, String name);
}
SubPublisherService:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class SubPublisherService {
private SubPublisherRepository subPublisherRepository;
#Autowired
public void setSubPublisherRepository(SubPublisherRepository subPublisherRepository) {
this.subPublisherRepository = subPublisherRepository;
}
public SubPublisher save(SubPublisher toSave) {
return subPublisherRepository.save(toSave);
}
public void delete(SubPublisher toDelete) {
subPublisherRepository.delete(toDelete);
}
/**
* This method will either find any existing SubPublisher by the Name and the Publisher or create one if none existed.
*/
public SubPublisher getOrCreateSubPublisher(Publisher publisher, String name) {
SubPublisher subPublisher = subPublisherRepository.findByPublisherAndAndName(publisher, name);
if(subPublisher == null) {
subPublisher = new SubPublisher();
subPublisher.setPublisher(publisher);
subPublisher.setName(name);
subPublisher = save(subPublisher);
}
return subPublisher;
}
public Iterable<SubPublisher> getAll() {
return subPublisherRepository.findAll();
}
}
In the html i changed <input type="text" class="form-control" th:field="*{subPublishers[__${stat.index}__].name}" /> to <input type="text" class="form-control" th:field="*{subPublishers[__${stat.index}__].}" />
I am getting this rare exception when I am trying to update an entity. I am working with ASP.NET MVC 5, EF 6.1, Identity and the patterns repository and unit of work.
I followed this cool tutorial from Tim.
I have all the work done in 4 separate projects (UI, Entities, Domain and DataAccess), I included Tim solution to use Users and roles.
My Entities:
public class Turno : IEntity
{
public Turno()
{
//Medico = new Medico();
//Consultorio = new Consultorio();
}
public Int64 Id { get; set; }
[Required]
public DateTime Fecha { get; set; }
[Required]
[StringLength(10)]
public string Hora { get; set; }
[Required]
public Medico Medico { get; set; }
[Required]
public Consultorio Consultorio { get; set; }
[Required]
public EstadoTurno Estado { get; set; }
public virtual Paciente Paciente { get; set; }
}
namespace TurnosMedicos.Entities
{
[Table("Medicos")]
public class Medico: Persona
{
public Medico()
{
Especialidades = new List<Especialidad>();
TurnosDisponibles = new List<Turno>();
Consultorios = new List<Consultorio>();
Telefonos = new List<Telefono>();
PlanesAtendidos = new List<PrepagaPlan>();
}
[Required]
[StringLength(10)]
public string Matricula { get; set; }
[Required]
public decimal PrecioTurno { get; set; }
public virtual List<Especialidad> Especialidades { get; set; }
public virtual List<Turno> TurnosDisponibles { get; set; }
public virtual List<Consultorio> Consultorios { get; set; }
public List<PrepagaPlan> PlanesAtendidos { get; set; }
public override string ToString()
{
return Apellido + ", " + Nombres;
}
}
}
namespace TurnosMedicos.Entities
{
public class Paciente: Persona
{
public Paciente()
{
HistoriaClinica = new List<Consulta>();
Turnos = new List<Turno>();
Telefonos = new List<Telefono>();
PlanesSalud = new List<PrepagaPlan>();
TurnosAusentes = new List<TurnoInformadoAusente>();
}
public virtual List<TurnoInformadoAusente> TurnosAusentes { get; set; }
public virtual List<Consulta> HistoriaClinica { get; set; }
public virtual List<Turno> Turnos { get; set; }
public override string ToString()
{
return Apellido + ", " + Nombres;
}
public List<PrepagaPlan> PlanesSalud { get; set; }
public PrepagaPlan PlanPredeterminado()
{
if(PlanesSalud.Count()>0)
{
return PlanesSalud[0];
}
return null;
}
public string TelefonosRapido()
{
System.Text.StringBuilder tel = new System.Text.StringBuilder();
foreach(var t in this.Telefonos)
{
tel.Append(t.Numero + " (" + t.Tipo + ")");
tel.AppendLine();
}
return tel.ToString();
}
/// <summary>
/// Porcentaje de Asistencia
/// </summary>
[NotMapped]
public decimal Ranking
{
get{
if (TurnosAusentes.Count == 0)
{
return 100;
}
else{
return (100 - (Decimal.Divide(TurnosAusentes.Count, Turnos.Count) * 100));
}
}
}
}
}
My Repositories:
public class MedicosRepository: Repository<Medico> //, IMedicoRepository
{
internal MedicosRepository(ApplicationDbContext context)
: base(context)
{
}
public IQueryable<Medico> Find(System.Linq.Expressions.Expression<Func<Medico, bool>> predicate)
{
return Set.Where(predicate);
}
public override List<Medico> GetAll()
{
return Set.Include("Telefonos")
.Include("PlanesAtendidos")
.Include("Consultorios")
.Include("Consultorios.Telefonos")
.Include("TurnosDisponibles.Paciente.Telefonos")
.ToList();
}
public IQueryable<Medico> FindAll()
{
return Set.Include("Telefonos")
.Include("PlanesAtendidos")
.Include("Consultorios")
.Include("Consultorios.Telefonos")
.Include("TurnosDisponibles.Paciente.Telefonos");
}
public override Medico FindById(object id)
{
Int64 Id = Int64.Parse(id.ToString());
return Set.Include("Telefonos")
.Include("Consultorios")
.Include("Consultorios.Telefonos")
.Include("PlanesAtendidos")
.Include("TurnosDisponibles.Paciente.Telefonos")
.Single(o => o.Id == Id);
}
}
TurnosRepository:
namespace TurnosMedicos.DataAccess.Repositories
{
internal class TurnosRepository: Repository<Turno>
{
public TurnosRepository(ApplicationDbContext context): base(context)
{
}
public override List<Turno> GetAll()
{
return Set.Include("Medico")
.Include("Paciente")
.Include("Consultorio").ToList();
}
public override Turno FindById(object id)
{
Int64 Id = Int64.Parse(id.ToString());
return Set.Include("Medico")
.Include("Paciente")
.Include("Consultorio")
.Single(o => o.Id == Id);
}
}
}
User repository:
namespace TurnosMedicos.DataAccess.Repositories
{
internal class UserRepository : Repository<User>, IUserRepository
{
internal UserRepository(ApplicationDbContext context)
: base(context)
{
}
public User FindByUserName(string userName)
{
return Set.Include("Medico")
.Include("Paciente")
.FirstOrDefault(x => x.UserName == userName);
}
public Task<User> FindByUserNameAsync(string userName)
{
return Set.FirstOrDefaultAsync(x => x.UserName == userName);
}
public Task<User> FindByEmailAsync(System.Threading.CancellationToken cancellationToken, string email)
{
return Set.FirstOrDefaultAsync(x => x.Email == email, cancellationToken);
}
public User FindByEmail(string email)
{
return Set.Include("Medico")
.Include("Medico.Telefonos")
.Include("Medico.Especialidades")
.Include("Medico.TurnosDisponibles")
.Include("Medico.Consultorios")
.Include("Medico.PlanesAtendidos")
.Include("Paciente")
.Include("Paciente.Turnos")
.Include("Paciente.PlanesSalud")
.Include("Paciente.HistoriaClinica")
.Include("Paciente.TurnosAusentes")
.Include("Paciente.Telefonos")
.Include("Roles")
.FirstOrDefault(u => u.Email == email);
}
}
}
My Context:
namespace TurnosMedicos.DataAccess
{
internal class ApplicationDbContext : DbContext
{
internal ApplicationDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
}
public ApplicationDbContext(): base("TurnosMedicosCn")
{
}
public IDbSet<User> Users { get; set; }
public IDbSet<Role> Roles { get; set; }
public IDbSet<ExternalLogin> Logins { get; set; }
public DbSet<Paciente> Pacientes { get; set; }
public DbSet<Medico> Medicos { get; set; }
public DbSet<Turno> Turnos { get; set; }
public DbSet<Consulta> Consultas { get; set; }
public DbSet<Consultorio> Consultorios { get; set; }
public DbSet<Especialidad> Especialidades { get; set; }
public DbSet<Prepaga> Prepagas { get; set; }
public DbSet<PrepagaPlan> Planes { get; set; }
public DbSet<Registro> RegistrosFacturacion { get; set; }
public DbSet<Empresa> Empresas { get; set; }
public DbSet<Recomendado> Recomendados { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new UserConfiguration());
modelBuilder.Configurations.Add(new RoleConfiguration());
modelBuilder.Configurations.Add(new ExternalLoginConfiguration());
modelBuilder.Configurations.Add(new ClaimConfiguration());
}
}
}
My Unit Of Work
namespace TurnosMedicos.DataAccess
{
public class SQLUnitOfWork: IUnitOfWork
{
private readonly ApplicationDbContext _context;
PacientesRepository _pacientes = null;
//MedicosRepository _medicos = null;
IRepository<Medico> _medicos = null;
TurnosRepository _turnos = null;
EspecialidadRepository _especialidades = null;
PrepagasRepository _prepagas = null;
PrepagaPlanesRepository _planes = null;
RegistrosFacturacionRepository _registroFacturacion = null;
RecomendadosRepository _recomendados = null;
private IExternalLoginRepository _externalLoginRepository;
private IRoleRepository _roleRepository;
private IUserRepository _userRepository;
public SQLUnitOfWork(string nameOrConnectionString)
{
_context = new ApplicationDbContext(nameOrConnectionString);
}
public IRepository<Turno> Turnos
{
get { return _turnos ?? (_turnos = new TurnosRepository(_context)); }
}
public IRepository<Paciente> Pacientes
{
get
{
if(_pacientes==null)
{
_pacientes = new PacientesRepository(_context);
}
return _pacientes;
}
}
public IRepository<Medico> Medicos
{
get { return _medicos ?? (_medicos = new MedicosRepository(_context)); }
}
public IRepository<Especialidad> Especialidades
{
get
{
if (_especialidades == null)
{
_especialidades = new EspecialidadRepository(_context);
}
return _especialidades;
}
set
{
throw new NotImplementedException();
}
}
public IRepository<Prepaga> Prepagas {
get {
if (_prepagas == null)
{
_prepagas = new PrepagasRepository(_context);
}
return _prepagas;
}
set { throw new NotImplementedException(); }
}
public IRepository<PrepagaPlan> Planes {
get
{
if (_planes == null)
{
_planes = new PrepagaPlanesRepository(_context);
}
return _planes;
}
}
public IRepository<Registro> RegistrosFacturacion
{
get
{
if(_registroFacturacion == null)
{
_registroFacturacion = new RegistrosFacturacionRepository(_context);
}
return _registroFacturacion;
}
}
public IRepository<Recomendado> Recomendados
{
get
{
if (_recomendados == null)
{
_recomendados = new RecomendadosRepository(_context);
}
return _recomendados;
}
}
public IExternalLoginRepository ExternalLoginRepository
{
get { return _externalLoginRepository ?? (_externalLoginRepository = new ExternalLoginRepository(_context)); }
}
public IRoleRepository RoleRepository
{
get { return _roleRepository ?? (_roleRepository = new RoleRepository(_context)); }
}
public IUserRepository UserRepository
{
get { return _userRepository ?? (_userRepository = new UserRepository(_context)); }
}
public int SaveChanges()
{
try
{
return _context.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
Exception raise = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
string message = string.Format("{0}:{1}",
validationErrors.Entry.Entity.ToString(),
validationError.ErrorMessage);
raise = new InvalidOperationException(message, raise);
}
}
throw raise;
}
}
public Task<int> SaveChangesAsync()
{
try
{
return _context.SaveChangesAsync();
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
Exception raise = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
string message = string.Format("{0}:{1}",
validationErrors.Entry.Entity.ToString(),
validationError.ErrorMessage);
raise = new InvalidOperationException(message, raise);
}
}
throw raise;
}
}
public Task<int> SaveChangesAsync(System.Threading.CancellationToken cancellationToken)
{
return _context.SaveChangesAsync(cancellationToken);
}
public void Dispose()
{
_externalLoginRepository = null;
_roleRepository = null;
_userRepository = null;
_turnos = null;
_pacientes = null;
_especialidades = null;
_planes = null;
_prepagas = null;
_recomendados = null;
_registroFacturacion = null;
}
}
}
And Finally, the Domain class where I am trying to get things done
IUnitOfWork unitofwork = null;
IRepository<Paciente> repositoryPacientes = null;
//IMedicoRepository repositoryMedicos = null;
IRepository<Medico> repositoryMedicos = null;
IRepository<Turno> repositoryTurnos = null;
IRepository<Especialidad> repositoryEspecialidad = null;
IRepository<Registro> repositoryRegistroFacturacion = null;
IRepository<Recomendado> repositoryRecomendados = null;
public TurnosManager(IUnitOfWork _unitOfWork)
{
unitofwork = _unitOfWork;
repositoryPacientes = unitofwork.Pacientes;
repositoryMedicos = unitofwork.Medicos;
repositoryTurnos = unitofwork.Turnos;
repositoryEspecialidad = unitofwork.Especialidades;
repositoryRegistroFacturacion = unitofwork.RegistrosFacturacion;
repositoryRecomendados = unitofwork.Recomendados;
}
private bool AsignarTurno(Paciente p, Turno t)
{
if(t.Fecha.Date < DateTime.Now.Date)
{
throw new TurnoInvalidoException("No se puede seleccionar un turno para una fecha en el pasado.");
}
// Ver tema de la hora para la fecha actual
t.Estado = EstadoTurno.Reservado;
t.Paciente = p;
p.Turnos.Add(t);
//repositoryTurnos.Update(t);
unitofwork.SaveChanges();
string planMedico = "Privado";
if (p.PlanesSalud.Count > 0)
{
planMedico = p.PlanesSalud[0].NombrePlan;
}
RegisstrarParaFacturacion(t, planMedico);
ReservaVM obj = new ReservaVM();
obj.Paciente = p;
obj.MedicoSeleccionado = t.Medico;
obj.TurnoSeleccionado = t;
EnviarEmail(obj);
return true;
}
The problem occurs in line unitofwork.SaveChanges();
I get the exception: "You can not define the relationship between two objects because they are associated with different ObjectContext objects" but I only have "ApplicationDbContext" in my code.
The problem is that you have one type which is ApplicationDbContext, but there are two instances of that context. One instantiated to fetch Pacient p and another one for Turno t.
Where is the AsignarTurno(Paciente p, Turno t) called from?
If this is code first you should add
public int PacienteId { get; set; }
to class Turno.
If your classes are well define you should only need to persist the relation on one side, so in the AsignarTurno function instead of:
t.Paciente = p;
p.Turnos.Add(t);
you should only have
t.PacienteId = p.Id;
This would do what you need, assuming that p and t both exist the database.
The problem is since my POJO/Domain classes are in java (obvious actually but just to make it clear) the sub-object that i use does'nt show up properly in the form when I click on available controllers: Eg: Patient has address -->> address is a sub-object in patient:
The address field shows a blank dropdown. How do i resolve this?
I am using def scaffold= in the controller.
package pojo;
public class Address {
private int id;
private String street;
private String city;
private String state;
private String country;
private Integer clinicid;
private Integer patientid;
public Address(){
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Integer getClinicid() {
return clinicid;
}
public void setClinicid(Integer clinicid) {
this.clinicid = clinicid;
}
public Integer getPatientid() {
return patientid;
}
public void setPatientid(Integer patientid) {
this.patientid = patientid;
}
}
package pojo;
public class Clinic {
private int id ;
private String clinicname ;
private Address address;
public int contactNumber;
public Clinic() {
address=new Address();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getClinicname() {
return clinicname;
}
public void setClinicname(String clinicname) {
this.clinicname = clinicname;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
address.setClinicid(this.id);
this.address = address;
}
public int getContactNumber() {
return contactNumber;
}
public void setContactNumber(int contactNumber) {
this.contactNumber = contactNumber;
} }
package pojo;
import java.util.*;
public class Doctor {
private int id ;
private Date dateOfBirth ;
private String username;
private String password ;
//private String name ;
private int contactNumber ;
private String specialization ;
public Clinic clinic;
public Doctor(){
clinic=new Clinic();
}
public Clinic getClinic() {
return clinic;
}
public void setClinic(Clinic clinic) {
this.clinic = clinic;
}
/*public Doctor() {
}*/
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getContactNumber() {
return contactNumber;
}
public void setContactNumber(int contactNumber) {
this.contactNumber = contactNumber;
}
public String getSpecialization() {
return specialization;
}
public void setSpecialization(String specialization) {
this.specialization = specialization;
}
}
package pojo;
import java.util.*;
public class Patient {
private int id;
private Date dateOfBirth;
private Date registrationDate;
private String name ;
public int contactNumber;
public enum sexenum {MALE, FEMALE}
public sexenum sex;
private Address address;
private Clinic clinic;
private Doctor doctor;
public Patient(){
clinic=new Clinic();
doctor=new Doctor();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public Date getRegistrationDate() {
return registrationDate;
}
public void setRegistrationDate(Date registrationDate) {
this.registrationDate = registrationDate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getContactNumber() {
return contactNumber;
}
public void setContactNumber(int contactNumber) {
this.contactNumber = contactNumber;
}
public sexenum getSex() {
return sex;
}
public void setSex(sexenum sex) {
this.sex = sex;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
address.setPatientid(this.id);
this.address = address;
}
public Clinic getClinic() {
return clinic;
}
public void setClinic(Clinic clinic) {
this.clinic = clinic;
}
public Doctor getDoctor() {
return doctor;
}
public void setDoctor(Doctor doctor) {
this.doctor = doctor;
}
}
patient [ one to one with ] address;.
clinic [ one to one with ] address;.
doctorid [ foreign key many to one]where ever referenced.
clinic id [foreign key many to one ] where ever referenced.
As far as I know, Grails only supports GORM-mappings (http://grails.org/doc/latest/guide/single.html#ormdsl) and hibernate mappings (http://grails.org/doc/latest/guide/single.html#hibernate)
I don't think the mappings you provide are valid for scaffolding.
namespace NinjectDemo
{
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
public interface IValueCalculator
{
decimal ValueProducts(params Product[] products);
}
public class LinqValueCalculator : IValueCalculator
{
private IDiscountHelper discounter;
public LinqValueCalculator(IDiscountHelper discountParam)
{
discounter = discountParam;
}
public decimal ValueProducts(params Product[] products)
{
return discounter.ApplyDiscount(products.Sum(p => p.Price));
}
}
public class ShoppingCart
{
private IValueCalculator calculator;
public ShoppingCart(IValueCalculator calcParam)
{
calculator = calcParam;
}
public decimal CalculateStockValue()
{
Product[] products = {
new Product() {Name = "Kajak", Price = 275M},
new Product() {Name = "Lifejacket", Price = 48.95M},
new Product() {Name = "Soccer ball", Price = 19.50M},
new Product() {Name = "Stadium", Price = 79500M}
};
decimal totalValue = calculator.ValueProducts(products);
return totalValue;
}
}
public interface IDiscountHelper
{
decimal ApplyDiscount(decimal totalParam);
}
public class DefaultDiscountHelper: IDiscountHelper
{
public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (10m / 100m * totalParam));
}
}
class Program
{
static void Main(string[] args)
{
IKernel ninjectKernel = new StandardKernel();
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
ninjectKernel.Bind<IValueCalculator>().To<DefaultDiscountHelper>();//error
IValueCalculator calcImpl = ninjectKernel.Get<IValueCalculator>();
ShoppingCart cart = new ShoppingCart(calcImpl);
Console.WriteLine("Total: {0:c}", cart.CalculateStockValue());
}
}
}
ninjectKernel.Bind().To();
write error, what could be the problem?
DefaultDiscountHelper does not implement IValueCalculator
probably you want to bind IDiscountHelper