th:checked throws exception - thymeleaf

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>

Related

error 'The operation cannot be completed because the DbContext has been disposed.'

I am using generic repository and unit of work in asp.net MVC. when I want to access the context in controller I get this error:
'The operation cannot be completed because the DbContext has been disposed.'
however when I comment this line:
'Database.SetInitializer(new MigrateDatabaseToLatestVersion());'
in Global.asax the error will fix. but as soon as i uncomment that line the error still happening.
here is generic repository:
public class GenericRepository<TEntity> where TEntity : class
{
internal ZarinParse_Context context;
internal DbSet<TEntity> dbSet;
public GenericRepository(ZarinParse_Context context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters)
{
return dbSet.SqlQuery(query, parameters).ToList();
}
public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Update(TEntity entity)
{
dbSet.Attach(entity);
context.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entity)
{
if (context.Entry(entity).State == EntityState.Detached)
{
dbSet.Attach(entity);
}
dbSet.Remove(entity);
}
}
and unit of work:
public class UnitOfWork : IDisposable
{
private ZarinParse_Context context;
private RoleRepository roleRepository;
private UserRepository userRepository;
private UserRoleRepository userRoleRepository;
public UnitOfWork()
{
context = new ZarinParse_Context();
}
public RoleRepository RoleRepository
{
get
{
if (this.roleRepository == null)
{
this.roleRepository = new RoleRepository(context);
}
return roleRepository;
}
}
public UserRepository UserRepository
{
get
{
if (this.userRepository == null)
{
this.userRepository = new UserRepository(context);
}
return userRepository;
}
}
public UserRoleRepository UserRoleRepository
{
get
{
if (this.userRoleRepository == null)
{
this.userRoleRepository = new UserRoleRepository(context);
}
return userRoleRepository;
}
}
public void Save()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
RoleRepository Class:
public class RoleRepository : GenericRepository<Role>
{
public RoleRepository(ZarinParse_Context context)
: base(context)
{
}
}
my Context:
public class ZarinParse_Context : DbContext
{
public IDbSet<User> Users { get; set; }
public IDbSet<Role> Roles { get; set; }
public IDbSet<UserRole> UserRoles { get; set; }
public IDbSet<Product> Products { get; set; }
public IDbSet<Tag> Tags { get; set; }
public IDbSet<TagProduct> TagProducts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new UserConfig());
modelBuilder.Configurations.Add(new RoleConfig());
modelBuilder.Configurations.Add(new UserRoleConfig());
modelBuilder.Configurations.Add(new ProductConfig());
modelBuilder.Configurations.Add(new TagConfig());
modelBuilder.Configurations.Add(new TagProductConfig());
}
}
my Controller:
public class HomeController : Controller
{
UnitOfWork unitOfWork = new UnitOfWork();
public ActionResult Index()
{
var model = new Role() { Name = "User" };
unitOfWork.RoleRepository.Insert(model);
unitOfWork.Save();
return View();
}
protected override void Dispose(bool disposing)
{
unitOfWork.Dispose();
base.Dispose(disposing);
}
}
and Global.asax File:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ZarinParse_Context, Configuration>());
}
}
and Configuration :
public class Configuration : DbMigrationsConfiguration<ZarinParse_Context>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
AutomaticMigrationDataLossAllowed = false;
ContextKey = "ZarinParse.DomainClasses.Context.ZarinParse_Context";
}
protected override void Seed(ZarinParse_Context context)
{
InitializeAdmin(context: context,
roleName: "Admin",
userName: "soheil91141121#gmail.com",
password: "stb_91141121",
fullName: "سهیل تقی زاده بنگر",
mobileNumber: "09356336121",
newsEamilEnabled: true);
}
private void InitializeAdmin(ZarinParse_Context context, string roleName, string userName, string password, string fullName, bool newsEamilEnabled, string mobileNumber)
{
//Create Role Admin if it does not exist
var roleExist = context.Roles.Any(p => p.Name == roleName);
if (!roleExist)
{
var role = Role.Create();
role.Name = roleName;
context.Roles.Add(role);
context.SaveChanges();
}
//Create User if it does not exist
var userExist = context.Users.Any(p => p.UserName == userName);
if (!userExist)
{
var user = User.Create();
user.UserName = userName;
user.Email = userName;
user.Password = password.Encrypt();
user.FullName = fullName;
user.NewsEmailEnabled = newsEamilEnabled;
user.MobileNumber = mobileNumber;
context.Users.Add(user);
context.SaveChanges();
}
//Create UserRole if it does not exist
var role2 = context.Roles.Single(p => p.Name == roleName);
var user2 = context.Users.Single(p => p.UserName == userName);
var userRoleExist = context.UserRoles.Any(p => p.RoleId == role2.RoleId && p.UserId == user2.UserId);
if (!userRoleExist)
{
var userRole = UserRole.Create();
userRole.Role = role2;
userRole.User = user2;
context.UserRoles.Add(userRole);
context.SaveChanges();
}
context.Dispose();
}
}
The last line of InitializeAdmin disposes a context that is passed into the method.
Only dispose of objects that you have created, since you own the object's lifetime.
In other words, don't dispose of objects you don't own.

Joining of two table in objectDb

I have two table in objectDb employee and address, i want to join two tables and generate third table like emp_add.
Employee.java
#Entity
public class Employee
{
int empid;
String empname;
private Set<Address> address;
public Employee(int empid, String empname, Set address)
{
this.empid = empid;
this.empname = empname;
this.address = address;
}
#Id
public int getId()
{
return empid;
}
public void setId(int empid)
{
this.empid = empid;
}
public String getName()
{
return empname;
}
public void setName(String empname)
{
this.empname = empname;
}
#ManyToMany
#JoinTable(name = "emp_add",
joinColumns
= #JoinColumn(name = "empid", referencedColumnName = "empid"),
inverseJoinColumns
= #JoinColumn(name = "addid", referencedColumnName = "addid")
)
public Set getAddress()
{
return address;
}
public void setAddress(Set address)
{
this.address = address;
}
}
Address.java
#Entity
public class Address
{
int addid;
String city;
String houseno;
private Set<Employee> employee;
public Address(int addid, String city, String houseno,Set employee)
{
this.addid = addid;
this.city = city;
this.houseno = houseno;
}
public int getAdd()
{
return addid;
}
public void setAdd(int addid)
{
this.addid = addid;
}
public String getCity()
{
return city;
}
public void setCity(String city)
{
this.city = city;
}
public String getHouse()
{
return houseno;
}
public void setHouse(String houseno)
{
this.houseno = houseno;
}
#ManyToMany(mappedBy = "employee")
public Set getEmployee()
{
return employee;
}
public void setEmployee(Set employee)
{
this.employee = employee;
}
}
EmployyAdd.java
---------------
public class EmployyAdd
{
public static void main(String[] args)
{
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("$objectdb/db/empadd.odb");
EntityManager entitymanager = emfactory.createEntityManager();
entitymanager.getTransaction().begin();
Set<Employee> employee = new HashSet<Employee>();
Set<Address> address = new HashSet<Address>();
Employee emp = new Employee(1, "ram", employee);
Employee emp2 = new Employee(2, "john", employee);
Address add = new Address(1, "bbsr", "444", address);
Address add2 = new Address(2, "delhi", "747",address);
employee.add(emp);
employee.add(emp2);
address.add(add);
address.add(add2);
entitymanager.persist(emp);
entitymanager.persist(emp2);
entitymanager.persist(add);
entitymanager.persist(add2);
entitymanager.getTransaction().commit();
entitymanager.close();
emfactory.close();
}
}
After execute given codes it will generate output like
output:
packagename.Address
packagename.Employee
and inside Employee:
Your code includes several errors in setting the bidirectional relationship between Employee and Address.
Instead of:
Employee emp = new Employee(1, "ram", employee);
Employee emp2 = new Employee(2, "john", employee);
Address add = new Address(1, "bbsr", "444", address);
Address add2 = new Address(2, "delhi", "747",address);
it should be:
Employee emp = new Employee(1, "ram", address);
Employee emp2 = new Employee(2, "john", address);
Address add = new Address(1, "bbsr", "444", employee);
Address add2 = new Address(2, "delhi", "747",employee);
Instead of:
#ManyToMany(mappedBy = "employee")
it should be:
#ManyToMany(mappedBy = "address")
Always user generic collection parameters (e.g. Set<Address>) to avoid confusion and errors.
Following is the complete example after fixes (in one class format, in which the entity classes are inner static classes):
import java.util.*;
import javax.persistence.*;
public class F2221 {
public static void main(String[] args) {
EntityManagerFactory emfactory =
Persistence.createEntityManagerFactory(
"objectdb:$objectdb/db/empadd.tmp;drop");
EntityManager entitymanager = emfactory.createEntityManager();
entitymanager.getTransaction().begin();
Set<Employee> employee = new HashSet<Employee>();
Set<Address> address = new HashSet<Address>();
Employee emp = new Employee(1, "ram", address);
Employee emp2 = new Employee(2, "john", address);
Address add = new Address(1, "bbsr", "444", employee);
Address add2 = new Address(2, "delhi", "747",employee);
employee.add(emp);
employee.add(emp2);
address.add(add);
address.add(add2);
entitymanager.persist(emp);
entitymanager.persist(emp2);
entitymanager.persist(add);
entitymanager.persist(add2);
entitymanager.getTransaction().commit();
entitymanager.close();
emfactory.close();
}
#Entity
public static class Employee
{
int empid;
String empname;
private Set<Address> address;
public Employee(int empid, String empname, Set<Address> address)
{
this.empid = empid;
this.empname = empname;
this.address = address;
}
#Id
public int getId()
{
return empid;
}
public void setId(int empid)
{
this.empid = empid;
}
public String getName()
{
return empname;
}
public void setName(String empname)
{
this.empname = empname;
}
#ManyToMany
//#JoinTable(name = "emp_add",
// joinColumns
// = #JoinColumn(name = "empid", referencedColumnName = "empid"),
// inverseJoinColumns
// = #JoinColumn(name = "addid", referencedColumnName = "addid")
//)
public Set<Address> getAddress()
{
return address;
}
public void setAddress(Set<Address> address)
{
this.address = address;
}
}
#Entity
public static class Address
{
int addid;
String city;
String houseno;
private Set<Employee> employee;
public Address(int addid, String city, String houseno, Set<Employee> employee)
{
this.addid = addid;
this.city = city;
this.houseno = houseno;
}
public int getAdd()
{
return addid;
}
public void setAdd(int addid)
{
this.addid = addid;
}
public String getCity()
{
return city;
}
public void setCity(String city)
{
this.city = city;
}
public String getHouse()
{
return houseno;
}
public void setHouse(String houseno)
{
this.houseno = houseno;
}
#ManyToMany(mappedBy = "address")
public Set<Employee> getEmployee()
{
return employee;
}
public void setEmployee(Set<Employee> employee)
{
this.employee = employee;
}
}
}

Thymeleaf: Empty List doesn't show input fields

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}__].}" />

In Neo4J , Loading a Parent Node is loading duplicate children with id=null

Following is the model with A(UserN) and B(UserRoleN) as objects.
#NodeEntity()
public class UserN
{
#GraphId
private Long id;
#Relationship(type = "hasRole", direction = Relationship.OUTGOING)
private List<UserRoleN> role;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setRole(List<UserRoleN> role) {
this.role = role;
}
public List<UserRoleN> getRole() {
return role;
}
}
#NodeEntity()
public class UserRoleN
{
#GraphId
private Long id;
private String name;
public Long getName() {
return version;
}
public void setName(String name) {
this.name = name;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
}
In the database, following is graph structure:
A->B
While loading A, session.load(A.class, id, 1) , a total of 2 B-Objects are loading under A Object in which one of the B's ID is null and other B object ID is neo4j generated.
Unable to understand why the duplicate B is loaded where Database has only one B Object.

Grails: Integrating the Underlying Java(Spring+Hibernate) web app : sub-object not showing it s fields in form

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.

Resources