Primefaces Lazy Datatable Sort/Filter with table relation - Eclipselink - jpa

I have a lazy datatable of primefaces as follows:
<h:form id="form">
<p:dataTable value="#{beanReceipts.lazyModel}" paginator="true" rows="10" paginatorPosition="bottom"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="5,10,15" var="item" emptyMessage="#{bundle['NoData']}" reflow="true"
rowStyleClass="centered" styleClass="centered" lazy="true" resizableColumns="true">
<p:column style="width:24px" styleClass="centered">
<p:rowToggler/>
</p:column>
<p:column headerText="#{bundle['Name']}" filterBy="#{item.userId.name}" filterMatchMode="contains"
styleClass="centered" sortBy="#{item.userId.name}">
<h:outputText value="#{item.userId.name}"/>
</p:column>
<p:column headerText="#{bundle['Premium']}" styleClass="centered"
sortBy="#{item.userId.premiumExpiresAt}">
<p:selectBooleanCheckbox value="#{item.userId.premiumExpiresAt != null}" disabled="true"/>
</p:column>
<p:column headerText="#{bundle['Product']}" sortBy="#{item.productId}" styleClass="centered">
<h:outputText value="#{item.productId}"/>
</p:column>
<p:column headerText="#{bundle['AutoRenew']}" sortBy="#{item.autoRenew}" styleClass="centered">
<p:selectBooleanCheckbox value="#{item.autoRenew}" disabled="true"/>
</p:column>
<p:column headerText="#{bundle['ExpiresAt']}" styleClass="centered">
<h:outputText value="#{item.expiresAt}">
<f:convertDateTime type="date" pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
<p:column headerText="#{bundle['PurchasedAt']}" sortBy="#{item.purchasedAt}" styleClass="centered">
<h:outputText value="#{item.purchasedAt}">
<f:convertDateTime type="date" pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
<p:column headerText="#{bundle['Platform']}" sortBy="#{item.platform}" styleClass="centered">
<h:outputText value="#{item.platform}"/>
</p:column>
<p:rowExpansion>
<h:panelGrid columns="2" cellspacing="3" cellpadding="3">
<h:outputText value="#{bundle['OrderId']}" style="font-weight: bold"/>
<h:outputText value="#{item.orderId}"/>
<h:outputText value="#{bundle['PurchaseToken']}" style="font-weight: bold"/>
<h:outputText value="#{item.purchaseToken}"/>
<h:outputText value="#{bundle['IsProcessed']}" style="font-weight: bold"/>
<p:selectBooleanCheckbox value="#{item.purchasedAt != null}" disabled="true"/>
<h:outputText value="#{bundle['RawData']}" style="font-weight: bold"/>
<h:outputText value="#{item.rawData}"/>
</h:panelGrid>
<br/>
<p:commandButton actionListener="#{beanReceipts.checkPaymentForUser}" icon="ui-icon-refresh"
value="#{bundle['Validate']}"
oncomplete="window.location.reload();" onstart="PF('loadingDia').show();"
onsuccess="PF('loadingDia').hide();" style="margin: auto;display: block;"/>
</p:rowExpansion>
<p:column headerText="#{bundle['Options']}" styleClass="centered">
<p:commandButton icon="ui-icon-pencil" onsuccess="PF('editdia').show();" update=":editdia"
style="margin: 8px;">
<f:setPropertyActionListener value="#{item}" target="#{beanReceipts.editableItem}"/>
</p:commandButton>
<p:commandButton icon="ui-icon-trash" oncomplete="window.location.reload();"
action="#{beanReceipts.deleteEntity}"
onclick="if (!confirm('#{bundle['RemovePrompt']}'))return false;"
style="margin: 0 auto; text-align: center;">
<f:setPropertyActionListener value="#{item}" target="#{beanReceipts.removableItem}"/>
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
And here is my entity class:
public class UsersReceipts extends BaseEntity {
private static final long serialVersionUID = 1L;
#Basic(optional = false)
#Column(name = "RECEIPT_TYPE", nullable = false)
#Enumerated(EnumType.STRING)
private DBUserReceiptTypeEnum receiptType;
#Column(name = "AUTO_RENEW")
private Boolean autoRenew;
#Column(name = "ORDER_ID", length = 255)
private String orderId;
#Column(name = "PRODUCT_ID", length = 255)
private String productId;
#Column(name = "PACKAGE_NAME", length = 255)
private String packageName;
#Column(name = "EXPIRES_AT")
#Temporal(TemporalType.TIMESTAMP)
private Date expiresAt;
#Column(name = "PURCHASED_AT")
#Temporal(TemporalType.TIMESTAMP)
private Date purchasedAt;
#Lob
#Column(name = "PURCHASE_TOKEN", length = 65535)
private String purchaseToken;
#Basic(optional = false)
#Column(name = "PLATFORM", nullable = false, length = 8)
#Enumerated(EnumType.STRING)
private DBAppPlatformTypeEnum platform;
#Basic(optional = false)
#Lob
#Column(name = "RAW_DATA", nullable = false, length = 65535)
private String rawData;
#JoinColumn(name = "USER_ID", referencedColumnName = "ID", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private Users userId;
public UsersReceipts() {
}
public UsersReceipts(Integer id) {
this.id = id;
}
public UsersReceipts(Integer id, DBEntryStatusTypeEnum status, Date createdAt, DBAppPlatformTypeEnum platform,
DBUserReceiptTypeEnum receiptType, String rawData) {
this.id = id;
this.status = status;
this.createdAt = createdAt;
this.platform = platform;
this.receiptType = receiptType;
this.rawData = rawData;
}
public Boolean getAutoRenew() {
return autoRenew;
}
public void setAutoRenew(Boolean autoRenew) {
this.autoRenew = autoRenew;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public Date getExpiresAt() {
return expiresAt;
}
public void setExpiresAt(Date expiresAt) {
this.expiresAt = expiresAt;
}
public Date getPurchasedAt() {
return purchasedAt;
}
public void setPurchasedAt(Date purchasedAt) {
this.purchasedAt = purchasedAt;
}
public String getPurchaseToken() {
return purchaseToken;
}
public void setPurchaseToken(String purchaseToken) {
this.purchaseToken = purchaseToken;
}
public DBAppPlatformTypeEnum getPlatform() {
return platform;
}
public void setPlatform(DBAppPlatformTypeEnum platform) {
this.platform = platform;
}
public DBUserReceiptTypeEnum getReceiptType() {
return receiptType;
}
public void setReceiptType(DBUserReceiptTypeEnum receiptType) {
this.receiptType = receiptType;
}
public String getRawData() {
return rawData;
}
public void setRawData(String rawData) {
this.rawData = rawData;
}
#JsonIgnore
#XmlTransient
public Users getUserId() {
return userId;
}
public void setUserId(Users userId) {
this.userId = userId;
}
}
As you can already see my each 'receipt' object in datatable has a relation (ManyToOne) to a 'Users' object (class). In my datatable when I add:
#{item.userId.name}
it can show me user's name which the receipt belongs to.This also applies to
#{item.userId.premiumExpiresAt}
field in 2nd column. My problem is when I try to sort/filter 1st and 2nd column in my lazy datatable I get the following error because of relation:
SEVERE [http-nio-8080-exec-5] com.sun.faces.application.view.FaceletViewHandlingStrategy.handleRenderException Error Rendering View[/panel/receipts.xhtml]
java.lang.IllegalArgumentException: The attribute [userId.name] is not present in the managed type [EntityTypeImpl#422737256:UsersReceipts [ javaType: class entities.UsersReceipts descriptor: RelationalDescriptor(entities.UsersReceipts --> [DatabaseTable(test_esimibul.users_receipts)]), mappings: 14]].
at org.eclipse.persistence.internal.jpa.metamodel.ManagedTypeImpl.getAttribute(ManagedTypeImpl.java:148)
at org.eclipse.persistence.internal.jpa.querydef.FromImpl.get(FromImpl.java:312)
at core.AbstractFacade.getFilterCondition(AbstractFacade.java:175)
at core.AbstractFacade.count(AbstractFacade.java:131)
at core.panel.crud.LazyCrudBean$EntityLazyModel.load(LazyCrudBean.java:44)
As far as exception says that I need to include usersId (Users entity in my case) into the query, I couldn't achieve that. Here is my AbstractFacade's methods that perform lazy loading:
/**
* Returns paginated, sorted and filtered result list.
*
* #param startingAt
* #param maxPerPage
* #param sortField
* #param sortOrder
* #param filters
* #return
*/
#Override
public List<T> getAll(int startingAt, int maxPerPage, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
EntityManager em = getEntityManager();
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<T> cq = cb.createQuery(type);
Root<T> c = cq.from(type);
cq.where(getFilterCondition(cb, c, filters));
if (sortField != null) if (sortOrder == SortOrder.ASCENDING) cq.orderBy(cb.asc(c.get(sortField)));
else if (sortOrder == SortOrder.DESCENDING) cq.orderBy(cb.desc(c.get(sortField)));
List<T> results = em.createQuery(cq).setFirstResult(startingAt).setMaxResults(maxPerPage).getResultList();
em.close();
return results;
}
/**
* Returns the count of rows for the given filtering criterias.
*
* #param filters
* #return
*/
#Override
public int count(Map<String, Object> filters) {
EntityManager em = getEntityManager();
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<T> c = cq.from(type);
cq.where(getFilterCondition(cb, c, filters));
cq.select(cb.count(c));
int count = em.createQuery(cq).getSingleResult().intValue();
em.close();
return count;
}
/**
* Creates a dynamic filtering condition with the given params.
*
* #param cb
* #param c
* #param filters
* #return
*/
private Predicate getFilterCondition(CriteriaBuilder cb, Root<T> c, Map<String, Object> filters) {
Predicate filterCondition = cb.conjunction();
filters.put("status", DBEntryStatusTypeEnum.ACTIVE);
for (Map.Entry<String, Object> filter : filters.entrySet())
if (!filter.getValue().equals(""))
filterCondition = cb.and(filterCondition, cb.like(c.get(filter.getKey()), String.format("%%%s%%", filter.getValue())));
return filterCondition;
}
I need to know how to include relations when using them in a lazy datatable with sorting/filtering. Any help on solving the issue would be greatly appreciated.

I'm not sure filterBy works with lazy datatables. I have a similar case that I've solved by using new Primefaces 10 Datatable syntax:
<p:datatable value="#{myView.lazymodel}" var="entry">
<p:column field="entry.user.name"/>
....
This way, Primefaces detects relationship and filtering works just fine.

Related

JPA many to many relation: unable to insert into generated table

I have 2 entities "Entree" and "Emplacement":
#Entity
#Table(name = "ENTREE")
public class Entree {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID_ENTREE", updatable = false, nullable = false)
private long idEntree;
#Column(name = "NUM_DECLARATION", insertable=true, updatable=true, nullable=true)
private String numDeclaration;
#Column(name = "DATE_ENTREE", insertable=true, updatable=true, nullable=true)
private String dateEntree;
#Column(name = "TYPE_ENTREE", insertable=true, updatable=true, nullable=true)
private String typeEntree;
#Column(name = "NOM_ARTICLE", insertable=true, updatable=true, nullable=true)
private String nomArticle;
#Column(name = "TYPE_ARTICLE", insertable=true, updatable=true, nullable=true)
private String typeArticle;
#Column(name = "QUANTITE_ENTREE", insertable=true, updatable=true, nullable=true)
private int quantiteEntree;
#ManyToOne
#JoinColumn(name="idDossier", nullable=false)
private Dossier dossier;
#ManyToMany( fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinTable(name = "entree_emplacement",
joinColumns = {
#JoinColumn(name = "id_entree", referencedColumnName = "id_entree",
nullable = false, updatable = false)},
inverseJoinColumns = {
#JoinColumn(name = "id_emplacement", referencedColumnName = "id_emplacement",
nullable = false, updatable = false)})
private Set<Emplacement> emplacement = new HashSet<>();
public Entree() {
super();
}
public Entree( String numDeclaration, String dateEntree, String typeEntree, String nomArticle, String typeArticle, int quantiteEntree, boolean isDone) {
super();
this.numDeclaration = numDeclaration;
this.dateEntree = dateEntree;
this.typeEntree = typeEntree;
this.nomArticle = nomArticle;
this.typeArticle = typeArticle;
this.quantiteEntree = quantiteEntree;
}
public long getIdEntree() {
return idEntree;
}
public void setIdEntree(long idEntree) {
this.idEntree = idEntree;
}
public String getNumDeclaration() {
return numDeclaration;
}
public void setNumDeclaration(String numDeclaration) {
this.numDeclaration = numDeclaration;
}
public String getDateEntree() {
return dateEntree;
}
public void setDateEntree(String dateEntree) {
this.dateEntree = dateEntree;
}
public String getTypeEntree() {
return typeEntree;
}
public void setTypeEntree(String typeEntree) {
this.typeEntree = typeEntree;
}
public String getNomArticle() {
return nomArticle;
}
public void setNomArticle(String nomArticle) {
this.nomArticle = nomArticle;
}
public String getTypeArticle() {
return typeArticle;
}
public void setTypeArticle(String typeArticle) {
this.typeArticle = typeArticle;
}
public int getQuantiteEntree() {
return quantiteEntree;
}
public void setQuantiteEntree(int quantiteEntree) {
this.quantiteEntree = quantiteEntree;
}
public Dossier getDossier() {
return dossier;
}
public void setDossier(Dossier dossier) {
this.dossier = dossier;
}
public Set<Emplacement> getEmplacements() {
return emplacement;
}
public void addEmplacement(Emplacement emplacement) {
this.emplacement.add(emplacement);
emplacement.getEntrees().add(this);
}
public void removeEmplacement(Emplacement emplacement) {
this.emplacement.remove(emplacement);
emplacement.getEntrees().remove(this);
}
}
And here the second entity:
#Entity
#Table(name = "EMPLACEMENT")
public class Emplacement {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID_EMPLACEMENT", updatable = false, nullable = false)
private long idEmplacement;
#Column(name = "NUM_EMPLACEMENT", insertable=true, updatable=true, nullable=false)
private String numEmplacement;
#ManyToMany(mappedBy = "emplacement", fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
private Set<Entree> entree = new HashSet<>();
public Emplacement() {
}
public Emplacement( String numEmplacement) {
this.numEmplacement = numEmplacement;
}
public long getIdEmplacement() {
return idEmplacement;
}
public void setIdEmplacement(long idEmplacement) {
this.idEmplacement = idEmplacement;
}
public String getNumEmplacement() {
return numEmplacement;
}
public void setNumEmplacement(String numEmplacement) {
this.numEmplacement = numEmplacement;
}
public Set<Entree> getEntrees() {
return entree;
}
}
Here is my inserting code:
#PostMapping("/ajouterEntree")
public ResponseEntity<String> addEntree(#Valid Entree entree, BindingResult result,ModelMap modelMap, #RequestParam(name = "numDossier") String numDossier, #RequestParam(name = "emplacement") String liste_emplacements) {
Emplacement e = new Emplacement(liste_emplacements);
entree.getEmplacements().add(e);
entreeService.saveEntree(entree);
return new ResponseEntity<String>("ok" + result, HttpStatus.OK);
}
I am able to insert datas into Entree and Emplacement tables, but the third generated table named entree-emplacement is empty.
So how can I insert datas into generated table in #ManyToMany relation?
Thanks
Ok it's resolved. Here is my code:
if(!liste_emplacements.equals(""))
{
List<String> list = new ArrayList<String>(Arrays.asList(liste_emplacements.split(",")));
Emplacement[] emp = new Emplacement[list.size()];
for (int i=0; i<list.size() ;i++)
{
emp[i] = new Emplacement(Long.parseLong(list.get(i)));
entree.getEmplacements().add(emp[i]);
emp[i].getEntrees().add(entree);
}
}
entreeService.saveEntree(entree);
return new ResponseEntity<String>("ok" + result, HttpStatus.OK);

Spring Security configuration with the login form

It showing me the defult Login form and my login form i use the defult User name und passowrd to login to time. in the first time it sowing me my login form and when i try to login in the same default username and password it rturn alwas to the second login form with code stat:302. (i saved employee in the database but it givs me alwas err)
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
EmployeeDao employeeDao;
#Autowired
private DataSource dataSource;
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery("select username,password
from employees where username=?")
.authoritiesByUsernameQuery("select username, authority from employees where username=?")
.passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").failureUrl("/login?error=true").defaultSuccessUrl("/home", true)
.and()
.logout().logoutSuccessUrl("/login?logout=true") ;
}
}
My Controller:
#GetMapping({"/","/login"})
public String LoginForm() { return "login";}
#GetMapping("/home")
public String showhome(Model model) { return "index";}
My Entity:
#Entity
#Getter
#Setter
#Table(name = "employees")
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(name = "username", nullable = false)
private String username;
#Column(name = "password", nullable = false)
private String password;
#Column(name = "fullname", nullable = false)
private String fullname;
#Column(name = "authority", nullable = false)
private String authority;
#OneToMany(mappedBy = "employee", fetch = FetchType.EAGER)
#Cascade(CascadeType.ALL)
private List<Role> roles;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
My Login form:
<div class="divLogin" align="center">
<h1 clase="text-center">Login Page</h1>
<form class="addForm" th:action="#{/login}" method="post">
<fieldset>
<legend lase="text-center">Please Login</legend>
<input class="inputForm" type="text" id="username" name="username" placeholder="Username"/>
<input class="inputForm" type="password" id="password" name="password" placeholder="Passowrd"/>
<div class="divBottonLogin" align="center">
<button class="botten" type="submit">Log in</button>
</div>
</fieldset>
</form>
</div>

How to build a Simple search page using Spring MVC?

I have created webapp using Spring MVC and i have done the CRUD operations and now stuck with the search page.
I have already have coded below jsp and the controller.
JSP page body
<div align="center">
<h1>Search Items</h1>
<form action="search_1" method="get" modelAttribute="search">
<table>
<tr>
<td>Category:</td>
<td>
<select type="text" name="category_id">
<option value="Book">Book</option>
<option value="Audio Books">Audio Books</option>
<option value="Videos">Videos</option>
<option value="Music">Music</option>
</select>
</td>
</tr>
<tr>
<td>Publisher ID:</td>
<td>
<select type="text" name="publisher_id">
<option value="Harper Collins">Harper Collins</option>
<option value="Penguins">Penguins</option>
<option value="Franciscan Media">Franciscan Media</option>
<option value="Orbis">Orbis</option>
</select>
</td>
</tr>
<tr>
<td>Price Range:</td>
<td>Min: <input type="text" name="price_1"/> Max:
<input type="text" name="price_2"/></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="search"></td>
</tr>
</table>
</form>
</div>
Controller
#RequestMapping(value ="/search_1",method = RequestMethod.GET)
public ModelAndView search_1(HttpServletRequest request, HttpServletResponse response) {
String category_id = request.getParameter("category_id");
String publisher_id = request.getParameter("publisher_id");
int price = Integer.parseInt(request.getParameter("price"));
ModelAndView model = new ModelAndView();
model.setViewName("searchResult");
return model;
}
Items bean
package com.jwt.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "items")
public class Items implements Serializable {
private static final long serialVersionUID = -3465813074586302847L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column
private String ISBN;
#Column
private String title;
#Column
private String category_id;
#Column
private String Author;
#Column
private String publisher_id;
#Column
private float price;
#Column
private int stock;
#Column
private int photo_id;
public int getid() {
return id;
}
public void setid(int id) {
this.id = id;
}
public String getISBN() {
return ISBN;
}
public void setISBN(String ISBN) {
this.ISBN = ISBN;
}
public String gettitle() {
return title;
}
public void settitle(String title) {
this.title = title;
}
public String getcategory_id() {
return category_id;
}
public void setcategory_id( String category_id) {
this.category_id = category_id;
}
public String getAuthor() {
return Author;
}
public void setAuthor(String Author) {
this.Author = Author;
}
public String getpublisher_id() {
return publisher_id;
}
public void setpublisher_id(String publisher_id) {
this.publisher_id = publisher_id;
}
public float getprice() {
return price;
}
public void setprice(float price) {
this.price = price;
}
public int getstock() {
return stock;
}
public void setstock(int stock) {
this.stock = stock;
}
public int getphoto_id() {
return photo_id;
}
public void setphoto_id(int photo_id) {
this.photo_id = photo_id;
}
}
The search has to be done as per the search criteria on the JSP page. The results view can be on the same page. It really doesn't matter,
I am not sure why are you confused, but let's see if I can help.
In your controller, you have to extract all of the criteria correctly then retrieve the list of items using these criteria from your database. Create a method in a service class that takes these criteria as parameter and returns a list of items. Attached that item in model and display in "searchResult.jsp" page.
Here is a rough controller method that should handle your search
#RequestMapping(value = "/search_1", method = RequestMethod.GET)
public ModelAndView search(HttpServletRequest request) {
String categoryId = request.getParameter("category_id");
String publisherId = request.getParameter("publisher_id");
int minPrice = Integer.parseInt(request.getParameter("price_1"));
int maxPrice = Integer.parseInt(request.getParameter("price_2"));
List<Item> items = someService.getItems(categoryId, publisherId, minPrice, maxPrice);
ModelAndView model = new ModelAndView();
model.addObject("items", items);
model.setViewName("searchResult");
return model;
}

How to use findByxxx in our custom repository

I want to use findByHostObjectId to query MyEnity, but it says "No property hostObjectId found for type MyEntity"
I have my Rest Controller and #autowired MyRepository and I want to use MyRepository.findByHostObjectId(hostObjectId) to get MyEntity by request parameter(hostObjectId).
Repository
public interface MyRepository extends PagingAndSortingRepository<MyEntity, MyEntityId> {
//success
MyEntity findById(#Param("id") MyEntityId id);
//fail
MyEntity findByHostObjectId(#Param("hostObjectId") Integer hostObjectId);}
MyEntity
public class MyEntity implements java.io.Serializable {
private MyEntityId id;
public MyEntity() {
}
public MyEntity(MyEntityId id) {
this.id = id;
}
#EmbeddedId
public MyEntityId getId() {
return this.id;
}
public void setId(MyEntityId id) {
this.id = id;
}}
MyEntityId
#Embeddable
public class MyEntityId implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private int objectId;
private Integer hostObjectId;
private String hostName;
public MyEntityId() {
}
public MyEntityId(int objectId, Integer hostObjectId, String hostName) {
this.objectId = objectId;
this.hostObjectId = hostObjectId;
this.hostName = hostName;
}
public int getObjectId() {
return this.objectId;
}
public void setObjectId(int objectId) {
this.objectId = objectId;
}
public Integer getHostObjectId() {
return this.hostObjectId;
}
public void setHostObjectId(Integer hostObjectId) {
this.hostObjectId = hostObjectId;
}
public String getHostName() {
return this.hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}}
MyEntiry.hbm.xml
<hibernate-mapping>
<class name="sud.MyEntity" table="sud_view_myentity">
<composite-id name="id" class="sud.MyEntityId">
<key-property name="objectId" type="int">
<column name="OBJECT_ID" />
</key-property>
<key-property name="hostObjectId" type="java.lang.Integer">
<column name="HOST_OBJECT_ID" />
</key-property>
<key-property name="hostName" type="string">
<column name="HOST_NAME" length="64" />
</key-property>
</composite-id>
</class>
</hibernate-mapping>
Have you tried using property expressions for nested properties like findByMyEntityId_HostObjectId? I am not sure if this will work because embeddable classes id is special case.
Take a look at the examples in the link
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
Thanks very much
it works!!!
MyEntity findById_HostObjectId(#Param("hostObjectId") Integer hostObjectId);

NullPointerException on Restful Web Service from Database

I am very new on restful web service development. I tried to create one from database (local mysql) using Netbeans' template. I have a table called "workplaces" in db.
This is my WorkplacesFacadeREST.java:
#Stateless
#Path("com.rest.api.workplaces")
public class WorkplacesFacadeREST extends AbstractFacade<Workplaces> {
#PersistenceContext(unitName = "com.rest_hiring_challenge_war_1.0-SNAPSHOTPU")
private EntityManager em;
public WorkplacesFacadeREST() {
super(Workplaces.class);
}
#POST
#Override
#Consumes({"application/xml", "application/json"})
public void create(Workplaces entity) {
super.create(entity);
}
#PUT
#Path("{id}")
#Consumes({"application/xml", "application/json"})
public void edit(#PathParam("id") Integer id, Workplaces entity) {
super.edit(entity);
}
#DELETE
#Path("{id}")
public void remove(#PathParam("id") Integer id) {
super.remove(super.find(id));
}
#GET
#Path("{id}")
#Produces({"application/xml", "application/json"})
public Workplaces find(#PathParam("id") Integer id) {
return super.find(id);
}
#GET
#Override
#Produces({"application/xml", "application/json"})
public List<Workplaces> findAll() {
return super.findAll();
}
#GET
#Path("{from}/{to}")
#Produces({"application/xml", "application/json"})
public List<Workplaces> findRange(#PathParam("from") Integer from, #PathParam("to") Integer to) {
return super.findRange(new int[]{from, to});
}
#GET
#Path("count")
#Produces("text/plain")
public String countREST() {
return String.valueOf(super.count());
}
#Override
protected EntityManager getEntityManager() {
return em;
}
}
AbstractFacade.java:
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0] + 1);
q.setFirstResult(range[0]);
return q.getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}
My entity class Workplaces.java:
#Entity
#Table(name = "workplaces")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Workplaces.findAll", query = "SELECT w FROM Workplaces w"),
#NamedQuery(name = "Workplaces.findBySpId", query = "SELECT w FROM Workplaces w WHERE w.spId = :spId"),
#NamedQuery(name = "Workplaces.findByWorkers", query = "SELECT w FROM Workplaces w WHERE w.workers = :workers"),
#NamedQuery(name = "Workplaces.findByLatitude", query = "SELECT w FROM Workplaces w WHERE w.latitude = :latitude"),
#NamedQuery(name = "Workplaces.findByLongitude", query = "SELECT w FROM Workplaces w WHERE w.longitude = :longitude")})
public class Workplaces implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "sp_id")
private Integer spId;
#Basic(optional = false)
#NotNull
#Column(name = "workers")
private int workers;
#Basic(optional = false)
#NotNull
#Column(name = "latitude")
private float latitude;
#Basic(optional = false)
#NotNull
#Column(name = "longitude")
private float longitude;
public Workplaces() {
}
public Workplaces(Integer spId) {
this.spId = spId;
}
public Workplaces(Integer spId, int workers, float latitude, float longitude) {
this.spId = spId;
this.workers = workers;
this.latitude = latitude;
this.longitude = longitude;
}
public Integer getSpId() {
return spId;
}
public void setSpId(Integer spId) {
this.spId = spId;
}
public int getWorkers() {
return workers;
}
public void setWorkers(int workers) {
this.workers = workers;
}
public float getLatitude() {
return latitude;
}
public void setLatitude(float latitude) {
this.latitude = latitude;
}
public float getLongitude() {
return longitude;
}
public void setLongitude(float longitude) {
this.longitude = longitude;
}
#Override
public int hashCode() {
int hash = 0;
hash += (spId != null ? spId.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Workplaces)) {
return false;
}
Workplaces other = (Workplaces) object;
if ((this.spId == null && other.spId != null) || (this.spId != null && !this.spId.equals(other.spId))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.rest.api.Workplaces[ spId=" + spId + " ]";
}
}
So when I tried to access http://localhost:8080/hiring_challenge/com.rest.api.workplaces/count. It gives me HTTP 500 error tomcat page. Here is the exception details:
exception
org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
org.jboss.resteasy.core.SynchronousDispatcher.handleApplicationException(SynchronousDispatcher.java:365)
org.jboss.resteasy.core.SynchronousDispatcher.handleException(SynchronousDispatcher.java:233)
org.jboss.resteasy.core.SynchronousDispatcher.handleInvokerException(SynchronousDispatcher.java:209)
org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:557)
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:524)
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:126)
org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208)
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55)
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
root cause
java.lang.NullPointerException
com.rest.api.service.AbstractFacade.count(AbstractFacade.java:47)
com.rest.api.service.WorkplacesFacadeREST.countREST(WorkplacesFacadeREST.java:80)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:606)
org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:167)
org.jboss.resteasy.core.ResourceMethod.invokeOnTarget(ResourceMethod.java:269)
org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:227)
org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:216)
org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:542)
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:524)
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:126)
org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208)
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55)
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
I tried debugging it. It turns out my EntityManager em is null at run time. I checked PersistenceContext's unit name for my EntityManager em. It's same as specified as in my persistence.xml. I used Netbeans "Create RESTful Web Service from Database" to create these files from my local mysql db. Can someone give me some help please?
UPDATE:
I solved the problem by adding:
em = Persistence.createEntityManagerFactory("com.rest_hiring_challenge_war_1.0-SNAPSHOTPU").createEntityManager();
into my WorkplacesFacadeREST.java's getEntityManager() method. However, I am getting a page without any xml back though. So this is the new problem...Help?
UPDATE:
I was missing mySQL jdbc driver. After added that, the project worked.
mySQL jdbc driver was missing.