How to save a image (mediumblob) in db with JSF? - image

I have a few questions, I'm trying to find a tutorial of how to save a image onto a mediumblob column in my database using JSF, PrimeFaces (or if there is another way to do it) and Managed Bean, I know to do do it without JSF and Managed Bean, but since I'm new on these I stuck on a few things... I really have no idea of how to get the image from my JSF page, transform to a byte array and save it.
Please someone give a light.
Here is what I did, I'm sorry but I'm really new, so please help me.
JSF page:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:body>
<h:form>
<!-- <p:growl id="growl" showDetail="true" sticky="true" /> -->
<p:messages id="messages" showDetail="true" autoUpdate="true" closable="true" />
<h:panelGrid columns="3">
<h:outputText value="ID : "/>
<h:inputText id="txtId" name="txtId" value="${produtoMB.prodAtual.id}" readonly="true"/>
<p:message id="a" for="txtId"/>
<h:outputText value="Foto:"/>
<p:fileUpload id="txtFoto" name="txtFoto" value="${produtoMB.prodAtual.foto}" />
<p:message id="i" for="txtFoto" showSummary="true" showDetail="false"/>
<h:panelGroup>
<h:commandButton name="cmd" value="Insert" action="${produtoMB.insert()}"/>
</h:panelGroup>
</h:panelGrid>
</h:form>
</h:body>
</html>
My Entity
#Entity
public class Produto implements Serializable {
private static final long serialVersionUID = -8914597399554711634L;
private long id;
private Byte[] foto;
#Id
#GeneratedValue
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Lob
#Column(columnDefinition="mediumblob")
public Byte[] getFoto() {
return foto;
}
public void setFoto(Byte[] foto) {
this.foto = foto;
}
}
Managed Bean
#ManagedBean
#SessionScoped
public class ProdutoMB implements Serializable {
private static final long serialVersionUID = -3304202810037758438L;
private Produto prodAtual;
public ProdutoMB() {
prodAtual = new Produto();
prodDAO = new ProdutoDAOImpl();
}
public String insert() {
try {
prodDAO.insert( prodAtual );
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
}
Thank you!

byte[] photo is not accessible in JSF page. Use UploadedFile in ManagedBean for primefaces.
<p:fileUpload id="txtFoto" name="txtFoto" value="${produtoMB.file}" />
UploadedFile should be property of managed bean.
#ManagedBean
#SessionScoped
public class ProdutoMB implements Serializable {
private UploadedFile file;
// To save use InputStrem and byte[] from file.
}
Also define fileupload filter in web.xml
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

Related

Primefaces commandButton doesn't execute action on the Bean

I'm using SpringBoot 2.7.5 with Primefaces 12.0.0
I'm having some trouble with uploading a file to the server because if I put enctype="multipart/form-data", and I click on the button, the function specified on action attribute isn't called at all
The .xhtml
<!DOCTYPE html>
<ui:composition template="./template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<ui:define name="component">
<h:form id="form" enctype="multipart/form-data">
<p:fileUpload value="#{uploadFilesController.file}" mode="simple" skinSimple="true"/>
<p:commandButton value="Submit" ajax="false" action="#{uploadFilesController.parseFile}" skinSimple="true"/>
</h:form>
</ui:define>
</ui:composition>
The Bean
#Component
#ViewScoped
public class UploadFilesController implements Serializable {
private static final long serialVersionUID = 1L;
public UploadedFile file;
public UploadedFile getFile() {
System.out.println("getFile");
return file;
}
public void setFile(UploadedFile file) {
this.file = file;
System.out.println("SET!");
}
public void parseFile() {
System.out.println(file.getFileName());
if (file != null) {
FacesMessage message = new FacesMessage("Successful", file.getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, message);
}
}
#PostConstruct
public void init() {
}
}
When I click the button, after selecting some file the page updates but nothing happens on the backend.
If I remove the enctype="multipart/form-data", I get an error about the file is null.
Actually you can try my following example in order to create an automatic fileUpload.
web.xml (not sure if necessary)
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-lass>
</filter>
.xhtml
<h:form enctype="multipart/form-data">
<p:fileUpload id="uploadFile" mode="simple" skinSimple="true"
value="#{backing.file}" label="Select new file"
auto="true" listener="#{backing.handleFileUpload}"/>
</h:form>
backing.java
public void handleFileUpload(FileUploadEvent event) {
UploadedFile newfile = event.getFile();
//do some checks on newly added file
}

PrimeFaces Ajax listener in SelectOneMenu tag is not working with viewParam

I trying to use a selectOneMenu ajax listener but its not working when my page receives parameters.
In my tests I used the same example shown in PrimeFaces ShowCase page, but my page also receives parameters by viewParam and viewAction.
The first time the selectOneMenu is changed the action listener is triggered, and then it stops working.
My page:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org /TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<f:metadata>
<f:viewParam name="id" value="#{dropdownViewBean.id}" required="true" />
<f:viewAction action="#{dropdownViewBean.init}" />
</f:metadata>
<h:body>
<h:form>
<p:growl id="msgs" showDetail="true" />
<p:panel header="Select a Location" style="margin-bottom:10px;">
<h:panelGrid columns="2" cellpadding="5">
<p:outputLabel for="country" value="Country: " />
<p:selectOneMenu id="country" value="#{dropdownViewBean.country}" style="width:150px">
<p:ajax listener="#{dropdownViewBean.onCountryChange}" update="city" />
<f:selectItem itemLabel="Select Country" itemValue="" noSelectionOption="true" />
<f:selectItems value="#{dropdownViewBean.countries}" />
</p:selectOneMenu>
<p:outputLabel for="city" value="City: " />
<p:selectOneMenu id="city" value="#{dropdownViewBean.city}" style="width:150px">
<f:selectItem itemLabel="Select City" itemValue="" noSelectionOption="true" />
<f:selectItems value="#{dropdownViewBean.cities}" />
</p:selectOneMenu>
</h:panelGrid>
<p:separator />
<p:commandButton value="Submit" update="msgs" actionListener="#{dropdownViewBean.displayLocation}" icon="ui-icon-check" />
</p:panel>
</h:form>
</h:body>
</html>
And the bean:
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named(value = "dropdownViewBean")
#ViewScoped
public class DropdownViewBean implements Serializable {
private Map<String, Map<String, String>> data = new HashMap<String, Map<String, String>>();
private String country;
private String city;
private Map<String, String> countries;
private Map<String, String> cities;
private int id;
public DropdownViewBean() {
}
public void init() {
System.out.println("init id=" + id); // message is correctly shown when page starts
countries = new HashMap<String, String>();
countries.put("USA", "USA");
countries.put("Germany", "Germany");
countries.put("Brazil", "Brazil");
Map<String, String> map = new HashMap<String, String>();
map.put("New York", "New York");
map.put("San Francisco", "San Francisco");
map.put("Denver", "Denver");
data.put("USA", map);
map = new HashMap<String, String>();
map.put("Berlin", "Berlin");
map.put("Munich", "Munich");
map.put("Frankfurt", "Frankfurt");
data.put("Germany", map);
map = new HashMap<String, String>();
map.put("Sao Paolo", "Sao Paolo");
map.put("Rio de Janerio", "Rio de Janerio");
map.put("Salvador", "Salvador");
data.put("Brazil", map);
}
public Map<String, Map<String, String>> getData() {
return data;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Map<String, String> getCountries() {
return countries;
}
public Map<String, String> getCities() {
return cities;
}
public void onCountryChange() {
System.out.println("change"); // message is shown only the first time the combo is changed
if (country != null && !country.equals("")) {
cities = data.get(country);
} else {
cities = new HashMap<String, String>();
}
}
public void displayLocation() {
FacesMessage msg;
if (city != null && country != null) {
msg = new FacesMessage("Selected", city + " of " + country);
} else {
msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid", "City is not selected.");
}
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Important:
If I took out the metadata, viewParam and viewAction tags and mark the init() method with #PostConstruct then the sample works perfectly, but I need the page parameter.
I ask your help to solve it.
I have my distrust of the javax.faces.view.ViewScoped, I've just been too lazy to file an issue. For one thing, you don't have to use that type of ViewScoped yet; it was introduced to lead to the eventual deprecation of javax.faces.bean.ViewScoped. As at now, it's still very valid and just as applicable.
The only restriction on that annotation is that it's not applicable to a CDI bean and it's the only viewscope that will allow the #Inject annotation. It doesn't appear you're in need of it, so you should be able to safely remove it.
You can still pull the GET parameters from within your #PostConstruct, old school:
#PostConstruct
public void init(){
FacesContext ctxt = FacesContext.getCurrentInstance();
Map<String,String> requestParameters = ctxt.getExternalContext().getRequestParameterMap();
int id = Integer.parseInt(requestParameters.get("id"));
}
I had the same problem as you.
Replace the tag
<f:viewParam name="id" value="#{dropdownViewBean.id}" required="true" />
With
<f:viewParam name="id" value="#{dropdownViewBean.id}"/>
Unfortunately I don't have an explanation about this Bug

polling using f:ajax:: Hi Have been using setInterval and f:ajax to poll below is the code kindly advise what is wrong here:

Have used setInterval to call ajax method which will render the value on page or probably keep updating the page. But in debug the control does not comes to ajax method in bean. please advise the issue in below code
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<script>
setInterval(function() {
document.getElementById("changeme").click();
}, 3000);
</script>
<h3>JSF 2.0 + Ajax Hello World Example</h3>
<h:form>
<h:inputText id="name" value="#{helloBean.name}"></h:inputText>
<h:commandButton value="Welcome Me">
<f:ajax execute="name" render="output" />
</h:commandButton>
<h2><h:outputText id="output" value="#{helloBean.sayWelcome}" /></h2>
<h2><h:outputText id="countsee" value="#{helloBean.name}" /></h2>
<h:commandButton id="changeme" style="display:none">
<f:ajax execute="#this" listener="#{helloBean.updates}" render="countsee" ></f:ajax>
</h:commandButton>
</h:form>
</h:body>
</html>
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.AjaxBehaviorEvent;
import java.io.Serializable;
#ManagedBean
#SessionScoped
public class HelloBean implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private static int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSayWelcome(){
//check if null?
if("".equals(name) || name ==null){
return "";
}else{
return "Ajax message : Welcome " + name;
}
}
public void getUpdates(ActionBehaviorEvent event){
System.out.println("Printing"+count);
this.name=name+"agdam";
}
}
Try giving the below:
public void updates(ActionBehaviorEvent event)
The method name and name given in the listener should be same.

Primefaces fileupload resets on ajax update

I'm doing a multiple record editing in primefaces datatable, in the record editing there is file upload, which resets when the user presses the "add" button
The jsf code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form enctype="multipart/form-data">
<p:dataTable var="file" value="#{fileUpload.files}" id="uploadTable">
<p:column>
<p:inputText value="#{file.id}"/>
<p:inputText value="#{file.name}"/>
<p:fileUpload value="#{file.file}" mode="simple"/>
</p:column>
</p:dataTable>
<p:commandButton value="Add" action="#{fileUpload.add}" update="uploadTable" />
<p:commandButton action="#{fileUpload.submit}" value="Submit" ajax="false" />
</h:form>
</h:body>
</ui:composition>
Here's the controller:
#ManagedBean(name = "fileUpload")
#ViewScoped
public class DummyFileUpload implements Serializable {
private static final long serialVersionUID = 1L;
private List<File> files;
#PostConstruct
public void init() {
files = new ArrayList<DummyFileUpload.File>();
}
public void submit() {
// submit
}
public void add() {
files.add(new File());
}
public List<File> getFiles() {
return files;
}
public void setFiles(List<File> files) {
this.files = files;
}
public class File implements Serializable{
private static final long serialVersionUID = 2685385696849425824L;
private String id;
private String name;
private UploadedFile file;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public UploadedFile getFile() {
return file;
}
public void setFile(UploadedFile file) {
this.file = file;
}
}
}
The file upload control is reset when I do ajax call, I know it's a normal behavior but I'm asking if there's a known workaround for this situation and what could be the best practices for a complex business like this ?
This can be avoided by changing the file upload tag to the following:
<p:fileUpload fileUploadListener="#{fileUpload.add}" mode="advanced" />
This way the Add and Submit buttons as well as the AJAX update are not needed as the advanced version of the file upload will provide the same functionality.
In addition, in your DummyFileUpload bean you wall have to change the add function:
public void add(FileUploadEvent event) {
files.add(event.getFile());
}

org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions

Upon deleting an entity from the database I get the following exception:
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:410)
at org.hibernate.event.def.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:43)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:101)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:52)
at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:767)
at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:745)
at org.springframework.orm.hibernate3.HibernateTemplate$25.doInHibernate(HibernateTemplate.java:790)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:372)
at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:784)
at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:780)
at pl.edu.agh.adam.core.projects.dao.TagDAO.delete(TagDAO.java:98)
at pl.edu.agh.adam.core.projects.ProjectService.deleteTag(ProjectService.java:109)
at pl.edu.agh.adam.core.projects.web.TagPresenter.deleteTag(TagPresenter.java:97)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.el.parser.AstValue.invoke(AstValue.java:234)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297)
at org.apache.myfaces.view.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:83)
at javax.faces.component._MethodExpressionToMethodBinding.invoke(_MethodExpressionToMethodBinding.java:88)
at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:100)
at javax.faces.component.UICommand.broadcast(UICommand.java:120)
at javax.faces.component.UIData.broadcast(UIData.java:708)
at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:890)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:234)
at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1202)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:623)
at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:35)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:143)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:93)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)
I've dug deep and tried numerous solutions from the hibernate forum, but still I don't know what's going on and where the sessions are opened. The conditions under which this problem occurs:
First: OpenSessionInViewFilter - I've asked about it here. Everything seemed to work fine, but the deleting stopped all of a sudden the following day and all I've done is - I've added a non-connected class to a non-connected package.
<!-- Hibernate OpenSession Filter -->
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
Second: three-tier architecture. Here are the classes and the JSF page:
#Entity
#Table(name = "tag")
public class Tag implements Serializable {
private static final long serialVersionUID = 1L;
#ManyToMany(mappedBy = "tags", targetEntity = Project.class)
List<Project> projects = new ArrayList<Project>();
#Transient
public static final String PROP_ID = "id";
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "tag_id")
private Long id;
#Transient
public static final String PROP_NAME = "name";
#Column(name = "name", length = 25, unique = true)
private String name;
}
public class TagDAO extends HibernateDaoSupport implements ITagDAO {
#Override
public void create(Tag tag) {
getHibernateTemplate().save(tag);
}
#Override
public Tag getTag(String name){
Tag group = null;
DetachedCriteria criteria = DetachedCriteria.forClass(Tag.class);
criteria.add(Restrictions.eq("name", name));
List<Tag> tags = getHibernateTemplate().findByCriteria(criteria);
if ((tags != null) && (tags.size() > 0)) {
group = (Tag)tags.get(0);
}
return group;
}
#Override
public Tag getTag(Long id){
Tag group = null;
List<Tag> groups = getHibernateTemplate().find(
"from Tag where id = ?", id);
if ((groups != null) && (groups.size() > 0)) {
group = (Tag)groups.get(0);
}
return group;
}
#Override
public List<Tag> getTags(){
List<Tag> ret = getHibernateTemplate().find("from Tag");
System.out.println("Dao got "+ret.size()+" tags");
return ret;
}
#Override
public Integer getTagCount() {
DetachedCriteria criteria = DetachedCriteria.forClass(Tag.class);
criteria.setProjection(Projections.rowCount());
return (Integer)(getHibernateTemplate().findByCriteria(criteria).get(0));
}
#Override
public void delete(Tag group) {
getHibernateTemplate().delete(group);
}
#Override
public void update(Tag group) {
getHibernateTemplate().update(group);
}
#Override
public List<Tag> getTags(Integer first, Integer resultsPerPage,
String order, Boolean asc) {
DetachedCriteria criteria = DetachedCriteria.forClass(Tag.class);
if (asc){
criteria.addOrder(Order.asc(order));
}else{
criteria.addOrder(Order.desc(order));
}
return (List<Tag>)getHibernateTemplate().findByCriteria(criteria, first, resultsPerPage);
}
}
public class ProjectService implements IProjectService {
// Beans used by this service.
private IProjectDAO projectDao;
private ITagDAO tagDao;
#Override
public void createProject(Project project) throws AlreadyExistsException {
if (projectDao.getProject(project.getName()) != null) {
throw new AlreadyExistsException();
}
projectDao.addProject(project);
}
#Override
public List<Project> getProjects(Integer first, Integer howMany, String order,
boolean asc) {
return projectDao.getProjects(first, howMany, order, asc);
}
#Override
public Integer getProjectCount(){
return projectDao.getProjectCount();
}
#Override
public List<Project> getProjects() {
return projectDao.getAllProjects();
}
#Override
public void deleteProject(Long id) {
projectDao.removeProject(id);
}
#Override
public List<Tag> getTags() {
return tagDao.getTags();
}
#Override
public Tag getTag(String name){
return tagDao.getTag(name);
}
#Override
public void createTag(Tag tag) throws AlreadyExistsException {
if (tagDao.getTag(tag.getName()) != null) {
throw new AlreadyExistsException();
}
tagDao.create(tag);
}
#Override
public void deleteTag(Long id) {
tagDao.delete(tagDao.getTag(id));
}
#Override
public void updateTag(Tag tag) {
tagDao.update(tag);
}
}
#ManagedBean(name = "tagPresenter")
#RequestScoped
public class TagPresenter {
private List<Tag> tags;
private IProjectService projectService;
private Tag tag;
public void setTag(Tag tag) {
this.tag= tag;
}
public Tag getTag() {
return tag;
}
public TagPresenter() {
projectService = (IProjectService)ServiceFinder.getInstance()
.findBean("projectService");
tags = projectService.getTags();
}
private void refresh() {
tags = projectService.getTags();
}
public List<Tag> getTags() {
refresh();
return tags;
}
public void deleteTag() {
projectService.deleteTag(tag.getId());
}
}
finally the webpage:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.prime.com.tr/ui">
<ui:composition template="/templates/template.xhtml">
<ui:define name="head">
<title>Tags</title>
<link rel="stylesheet" type="text/css" href="#{facesContext.externalContext.requestContextPath}/styles/style.css"/>
</ui:define>
<ui:define name="content">
<h:form name="commandForm">
<p:dataTable var="tag" name="tagsList" value="${tagPresenter.tags}" paginator="true" rows="10" >
<p:column sortBy="#{tag.id}">
<f:facet name="header">
<h:outputText value="Id" />
</f:facet>
<h:outputText value="#{tag.id}" />
</p:column>
<p:column sortBy="#{tag.name}">
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{tag.name}" />
</p:column>
<p:column>
<h:commandLink action="#{tagDisplayer.showTag}" value="Modify">
<f:setPropertyActionListener target="#{tagDisplayer.tag}" value="#{tag}"/>
</h:commandLink>
<h:commandLink action="#{tagPresenter.deleteTag}" value="Delete">
<f:setPropertyActionListener target="#{tagPresenter.tag}" value="#{tag}"/>
</h:commandLink>
</p:column>
</p:dataTable>
</h:form>
<p:messages id="deletingError" showDetail="true"/>
</ui:define>
</ui:composition>
</html>
How is this problem caused and how can I solve it?
Fixes for this vary widely; it can be caused by problems like
bad session handling in your framework configuration
bad cascade settings, incorrect persistence settings
forgetting initialization of an Collection stored in a #ManyToOne database relation.
Make sure to check thoroughly for these cases in your mapping/hibernate configurations - before wasting hours. :D
Take a look at the HibernateTemplate chapter in the Spring documentation. Take a look at implementing a callback approach to access the session.
public void delete(final Tag group) throws Exception {
HibernateCallback callback = new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
Object groupObj = session.load(Tag.class, group.getId());
session.delete(groupObj);
return null;
}
};
getHibernateTemplate().execute(callback);
}
If the above is not what you are looking for you can still do a traditional approach as mentioned further down in the Spring documentation. In this approach don't use the HibernateTemplate to delete the object but use the Session from the HibernateDaoSupport to handle the delete.
public void delete(Tag group) throws Exception {
Session session = getSession(false);
Object groupObj = session.load(Tag.class, group.getId());
session.delete(groupObj);
}
This can be caused by calling session.disconnect() instead of session.close().

Resources