Jump to content


Check out our Community Blogs

dlinx90

Member Since 03 Apr 2012
Offline Last Active Aug 01 2012 01:19 AM
-----

Topics I've Started

Unique Combination Validation With Error Message In Hibernate

22 May 2012 - 01:16 AM

0 down vote favorite share [fb] share [tw]


Hi everyone,

I am developing a web application using Hibernate and Spring.

What I am wondering is how I can validate a unique combination of columns and show an error message to the user?

Currently I am using a custom validator to validate a unique field. I am wondering if it is possible to expand the validator to be able to handle combinations of columns that should be unique. The reason I am using a custom validator is because I want to display error messages to the user.

Here is the custom validator:

Unique.java
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = UniqueIdValidator.class)
@Documented
public @interface Unique {
    String message() default "already exits";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    /**
     * The mapped hibernate/jpa entity class
     */
    Class<?> entity();

    /**
     * The property of the entity we want to validate for uniqueness. Default name is "id"
     */
    String property() default "id";   
}

UniqueIdValidator.java
public class UniqueIdValidator implements ConstraintValidator<Unique, Serializable> {

    @Autowired(required=true)
    private SessionFactory sessionFactory;

    private Class<?> entityClass;
    private String uniqueField;

    public void initialize(Unique unique) {
        entityClass = unique.entity();
        uniqueField = unique.property();
    }

    @Transactional
    public boolean isValid(Serializable property, ConstraintValidatorContext cvContext) {
        Criteria crit = sessionFactory.getCurrentSession().createCriteria(entityClass);
        crit.add(Restrictions.eq(uniqueField, property));
        return crit.list().isEmpty();
    }

}

Is using a custom validator the easiest way to achieve my goal of both validation and error messages? I know i could use something like
@Table(name="table1",
uniqueConstraints = {@UniqueConstraint(columnNames={"column1", "column2"})}

to get the unique combination constraint but in that case is there any easy way to display an error message instead of just throwing an exception?
Thank you for your time and help.
/D

Nullpointerexception For Getastext In Propertyeditor

09 May 2012 - 02:21 PM

My hibernate mapping requires me to make a custom PropertyEditor for converting a String into an Object type (Document). The setAsText method is working fine and I'm able to save a document number to the database but when I try to display the document number it displays what i believe is an object address (testapp.domain.Document@eeccff..or something similar). When I add a getAsText method to the PropertyEditor it gives me the following error:


java.lang.NullPointerException
testapp.controller.DocumentRevisionController$DocumentPropertyEditor.getAsText(DocumentRevisionController.java:59)
Mapping:



    @OneToMany(mappedBy="document_number", cascade = CascadeType.ALL)
private Set<DocumentRevision> documentRevisions;

public void setDocumentRevisions(Set<DocumentRevision> documentRevisions){
    this.documentRevisions = documentRevisions;
}
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="DOCUMENT_NUMBER")
private Document document_number; 

public void setDocument_number(Document document_number){
    this.document_number = document_number;
}

public Document getDocument_number(){
    return document_number;
}

part of the Controller:


 class DocumentPropertyEditor extends PropertyEditorSupport {

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        Document value =  documentService.retrieveDocumentNumber(text);
        setValue(value);
    }

    @Override
    public String getAsText() {
        Document d = (Document) getValue();
        return d != null ? String.valueOf(d.getDocumentNumber()) : "";
    }

}


@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(Document.class, new DocumentPropertyEditor());
}


@RequestMapping(value="/add", method=RequestMethod.GET)
public String getDocumentRevision(Model model) {
DocumentRevision documentRevision = new DocumentRevision();
model.addAttribute("documentRevisionAttribute", documentRevision);
model.addAttribute("documentNumberList", documentService.retrieveAllDocumentNumbers());

return "new-documnent-revision";
}


@RequestMapping(value="/add", method=RequestMethod.POST)
public String postDocumentRevision(@ModelAttribute("documentRevisionAttribute") @Valid DocumentRevision documentRevision, BindingResult result) {

if(result.hasErrors()){
    return "new-document-revision";
}

documentRevisionService.createDocumentRevision(documentRevision);
return "redirect:/testapp/document-revision/list";  
}

Method that retrieves DocumentNumbers:

public void saveDocumentRevision(DocumentRevision documentRevision) {
    this.sessionFactory.getCurrentSession().save(documentRevision); 
}

Can anyone see where I've made a mistake and why the getAsText method gives the exception? Thank you for your help!

/D

Problem With Url Mapping In Spring Hibernate Wb Application

25 April 2012 - 09:00 AM

The spring/hibernate web application that I am creating is building and deploying correctly but I am having some problems when trying to access the jsp pages inside my WEB-INF/jsp folder. The test jsp page that I have placed in my WebContent folder opens correctly.
Here is my code:
new-customer.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
</head>
<body>

    <h1>Create New Customer</h1>

    <c:url var="saveUrl" value="/mis/start/newcustomer" />
    <form:form modelAttribute="customerAttribute" method="POST" action="${saveUrl}">
        <table>
            <tr>
                <td><form:label path="customerTargetId">Customer Target ID:</form:label></td>
                <td><form:input path="customerTargetId"/></td>
            </tr>

            <tr>
                <td><form:label path="customerName">Customer Name</form:label></td>
                <td><form:input path="customerName"/></td>
            </tr>

            <tr>
                <td><form:label path="customerCountry">Customer Country</form:label></td>
                <td><form:input path="customerCountry"/></td>
            </tr>
        </table>

        <input type="submit" value="Save" />
    </form:form>

</body>
</html>

start.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Test</h1>


<c:url var="addUrl" value="/mis/start/newcustomer" />
<p><a href="${addUrl}">Create new customer</a></p>
</body>
</html>

CustomerController
package testapp.mis.controller;

@Controller
@RequestMapping("/start")
public class CustomerController {

@Resource(name="customerService")
private CustomerService customerService;

@RequestMapping(value="/newcustomer", method=RequestMethod.GET)
public String getCustomer(Model model) {

    model.addAttribute("customerAttribute", new Customer());

    return "new-customer";
}

@RequestMapping(value="/newcustomer", method=RequestMethod.POST)
public String postCustomer(@ModelAttribute("customerAttribute") Customer customer) {
    customerService.createCustomer(customer);

    return "redirect:/mis/start";
}
}

web.xml
<?xml version="1.0" encoding="UTF-8"?>
      <web-app id="WebApp_ID" version="2.4" 
     xmlns="http://java.sun.com/xml/ns/j2ee" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

     <servlet>
     <servlet-name>mis</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <load-on-startup>1</load-on-startup>
     </servlet>

<servlet-mapping>
<servlet-name>mis</servlet-name>
<url-pattern>/mis/*</url-pattern>
</servlet-mapping>


    </web-app>


applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:mvc="http://www.springframework.org/schema/mvc"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
	  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	  http://www.springframework.org/schema/context
	  http://www.springframework.org/schema/context/spring-context-3.0.xsd
   http://www.springframework.org/schema/mvc
   http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
   

 <context:annotation-config />
 <context:component-scan base-package="testapp.mis" />
 <mvc:annotation-driven />
 <import resource="hibernate-context.xml" />
 
 </beans>

hibernate-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans"
	    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	    xmlns:p="http://www.springframework.org/schema/p"
	    xmlns:tx="http://www.springframework.org/schema/tx"
	    xmlns:context="http://www.springframework.org/schema/context"
	    xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd
	  ">
 
 <context:property-placeholder location="/WEB-INF/spring.properties" />
     
    <!-- Enables annotations for transaction management -->
    <tx:annotation-driven transaction-manager="transactionManager" />
    
    <!-- Declare the Hibernate SessionFactory for retrieving Hibernate sessions -->
     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
         p:dataSource-ref="dataSource"
         p:configLocation="${hibernate.config}"
         p:packagesToScan="testapp.mis"/>
 
 <!-- Declare a datasource that has pooling capabilities-->
 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close"
    p:driverClass="${app.jdbc.driverClassName}"
    p:jdbcUrl="${app.jdbc.url}"
    p:user="${app.jdbc.username}"
    p:password="${app.jdbc.password}"
    p:acquireIncrement="5"
    p:idleConnectionTestPeriod="60"
    p:maxPoolSize="100"
    p:maxStatements="50"
    p:minPoolSize="10" />
 
 <!-- Declare a transaction manager-->
 <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
		  p:sessionFactory-ref="sessionFactory" />
     
</beans>


hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
   
<hibernate-configuration>
  <session-factory>
 
   <!-- We're using MySQL database so the dialect needs to MySQL as well-->
    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
    <!-- Enable this to see the SQL statements in the logs-->
    <property name="show_sql">false</property>
    
    <!-- Remove after testing -->
    
    <!-- This will drop our existing database and re-create a new one.
	  Existing data will be deleted! -->
    <property name="hbm2ddl.auto">create</property>
  </session-factory>
</hibernate-configuration>

mis-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
	  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<!-- Declare a view resolver -->
 <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
	  p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />

</beans>

When I for example try to go to http://localhost/MIS/mis/start it tells me the page does not exist. (I have tried all combinations of localhost/MIS/start, localhost/mis/start/newcustomer etc.)



Can anyone see what the problem is?
Let me know if you need some other part of my code to help. Thank you!

Save Data From Both Dto And Services As A New Entry In A Table

19 April 2012 - 03:05 AM

I have been trying to find an example that will help me but I haven't been able to. Hopefully someone here can help me out.
In my application I have a DTO that I use for the view of my new-delivery page. Do I send the data to my DeliveryService through my controller: (not sure if this is right)
@Controller
public class DeliveryController {

  @Resource(name="deliveryService")
  private DeliveryService deliveryService;

  @RequestMapping(value="/initForm", method=RequestMethod.GET)
  public String getAdd(Model model){
  DeliveryDto form = new DeliveryDto();
  model.addAttribute("formData", form);
  return "----view----";

  }


  @RequestMapping(value="/postForm", method=RequestMethod.POST)
  public String postAdd(@ModelAttribute("formData") DeliveryDto form, Model model) {

  deliveryService.createDelivery(form.getCustomerName(), form.getCustomerCountry());

  return "----view----";
  }

}

Or do I retrieve that data in my DeliveryService?
The reason I am using a DTO is that I have some IDs in my Delivery table that I don't want the user to have to enter.
I use a customer Service+DTO to retrieve the ID corresponding to a pair of customerNames and customerCountries.
CustomerDAO:
@Repository
public class CustomerDaoImpl implements CustomerDao {

@Autowired(required=true)
private SessionFactory sessionFactory;

public Customer getCTID(String customerName, String customerCountry) { //Is it right to use a query here to get the Id?
    return (Customer) this.sessionFactory.getCurrentSession().createQuery(
               "select customerId from Customer where customerName = :name and customerCountry = :country")
               .setParameter("name", customerName).setParameter("country", customerCountry).uniqueResult();


    }
}

CustomerService:
@Service
public class CustomerServiceImpl implements CustomerService {

@Autowired(required=true)
private CustomerDao customerDao;

@Transactional
public Customer retrieveCTID(String customerName, String customerCountry) {
    return this.customerDao.getCTID(customerName, customerCountry);
}
}

I don't know how I would write the DeliveryService/DAO so that it takes some DTO data and the data from CustomerService and persists it as a new delivery in the DeliveryTable.
Thank you for your help!
/D

Populating Db Tables With Dropdown Menu Using Spring/hibernate

12 April 2012 - 01:38 PM

Hello everyone,

I was wondering how I would go about it if I wanted to make my web application so that I can populate my database using drop down menus which are filled by the existing objects from the relevant table?

I am creating a delivery management spring application using hibernate for ORM. Let's say for the sake of my question that I have two tables which look like this:

¦ Delivery_ID ¦ Product ¦ Customer_ID ¦ Date ¦
and
¦ Customer_ID ¦ CustomerName ¦ CustomerCountry¦

(The Customer_ID is unique to a CustomerName together with a CustomerCountry)

Since the users will for example not know the *Customer_ID* I want to be able to be able to have a page where the users are able enter a new delivery by filling in the Product, CustomerName, CustomerCountry and Date. My wish is for the first three to be drop down boxes where the user chooses from existing products, names and countries with the option to add a new one if it does not exist.

I have so far created the classes for the tables and mapped them using annotations.

My questions:

How do I deal with the fact that I want to add the new deliveries entering information into columns from different tables in the same view, excluding the Delivery_ID and Customer_ID? I would like for the application to automatically detect which Customer_ID the new delivery has by what Name and Country is entered (Given that combination already exists.)
Would I hard code this into my service layer or would it be something I would do in the Controller?

I realize this is a quite broad question so I don't expect any finished code for me to use (although I wouldn't say no to that ^^), just some tips on the architecture of my application.

Thank you for your time and help,

Best Regards,
D

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download