4

We have an existing hotel management system. I was asked to add a date validation in the "Create Accommodation" function in the system. The dialog looks like this:

enter image description here

The "End Date" is already validated as shown in the code below. The @Future annotation in Hibernate ensures that the date is in the future.

@NotNull
@Future
@DateTimeFormat(pattern = "dd/MM/yyyy")
@Temporal(TemporalType.DATE)
private Date endDate;

EDIT

I was asked to add a validation to the "Start date". Only the present or a future date is allowed. I tried to use a @Present annotation, but I guess there is no such thing. Unfortunately, @Future does not accept today's date. I am new to this kind of thing. So I hope someone can help me. Thank you.

thatguy
  • 21,059
  • 6
  • 30
  • 40
Kendall H.
  • 461
  • 3
  • 9
  • 21

3 Answers3

14

Hibernate

You can use

@CreationTimestamp
@Temporal(TemporalType.DATE)
@Column(name = "create_date")
private Date startDate;

or on update

@UpdateTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modify_date")
private Date startDate;

Java (JPA)

You can define a field Date startDate; and use

@PrePersist
protected void onCreateStartDate() {
startDate = new Date();

or on update

@PreUpdate
protected void onUpdateStartDate() {
startDate = new Date();

Update and example

After you have updated your question to not fix the start date to the present, you have to do a different approach. You need to write a custom validator to check if a date is now or in the future, like here.

Therefore you can introduce a new annotation in PresentOrFuture.java:

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PresentOrFutureValidator.class)
@Documented
public @interface PresentOrFuture {
    String message() default "{PresentOrFuture.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Then you have to define the validator in PresentOrFutureValidator.java:

public class PresentOrFutureValidator
    implements ConstraintValidator<PresentOrFuture, Date> {

    public final void initialize(final PresentOrFuture annotation) {}

    public final boolean isValid(final Date value,
        final ConstraintValidatorContext context) {

        // Only use the date for comparison
        Calendar calendar = Calendar.getInstance(); 
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);

        Date today = calendar.getTime();

        // Your date must be after today or today (== not before today)
        return !value.before(today) || value.after(today);

    }
}

Then you have to set:

@NotNull
@PresentOrFuture
@DateTimeFormat(pattern = "dd/MM/yyyy")
@Temporal(TemporalType.DATE)
private Date startDate;

Well, that was exhausive. I have not tested it myself, since I do not have a set-up to do so now, but it should work. I hope it helps.

Community
  • 1
  • 1
thatguy
  • 21,059
  • 6
  • 30
  • 40
  • Sorry for the late response Sir. This are the codes for startDate: http://pastie.org/10958151 I hope you can guide me. Thank you. – Kendall H. Nov 08 '16 at 13:05
  • If you can only allow the current timestamp, why do you have a setter method? Do you use Hibernate or JPA? – thatguy Nov 08 '16 at 13:23
  • Sorry, I edited my question Sir. It should accept current & future date. I use hibernate. – Kendall H. Nov 08 '16 at 13:44
  • Thank you for your help Sir! :) I will try this and update you. :) – Kendall H. Nov 08 '16 at 14:57
  • I tried your code Sir. I created a `PresentOrFuture.java` annotation and `PresentOrFutureValidator.java` class and added `@PresentOrFuture` but whenever I try to run the program I get this error: "The web application [/hms] registered the JDBC driver [org.hsqldb.jdbc.JDBCDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered." – Kendall H. Nov 09 '16 at 11:14
  • Still getting the same error when I run it in the command prompt Sir. Here's what happens when I "mvn tomcat7:run" it: http://pastie.org/private/cyemsdl01qerwy2dfvnpjw – Kendall H. Nov 10 '16 at 03:15
  • Do you have compile errors or warnings on this? I have changed the target annotation to `@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })`, I do not think this is the problem, but you can try. Which Java version do you use? – thatguy Nov 10 '16 at 18:36
  • I don't Sir. I tried it but I still get the same error Sir. Java 8. – Kendall H. Nov 11 '16 at 06:05
  • Sadly, I do not have the environment to test it myself, but since you use Java 8, I probably have another solution for you. The error `ASM ClassReader failed to parse class file` can come from using Java 8 in old versions of Spring, see [here](http://stackoverflow.com/questions/22526695/java-1-8-asm-classreader-failed-to-parse-class-file-probably-due-to-a-new-java) or [here](http://stackoverflow.com/questions/36820068/asm-classreader-failed-to-parse-class-file-probably-due-to-a-new-java-class-fi). Now, compile your code with Java 7 or *at last* upgrade to Spring 4. Update me, Madame. – thatguy Nov 11 '16 at 15:01
  • Sorry Sir, I was wrong the Java Version that I'm using is 1.6 and not 8. Other solution you suggest? Thank you for your patience Sir. – Kendall H. Nov 12 '16 at 03:17
  • What Spring version do you use? – thatguy Nov 12 '16 at 04:05
  • 3.2.8.RELEASE Sir. – Kendall H. Nov 12 '16 at 04:13
  • As already stated [here](http://stackoverflow.com/questions/22526695/java-1-8-asm-classreader-failed-to-parse-class-file-probably-due-to-a-new-java) by **ItayK**, this may be a bug concerning ASM in Spring 3.2.8. The best you can do is upgrade to Spring 4. – thatguy Nov 12 '16 at 13:42
7

Now, in the updated new validator version i.e.

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.4.Final</version>
</dependency>

via

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.0.Final</version>
</dependency>

we have @FutureOrPresent and many other helpful annotations that you can use.

Ankit Bhatnagar
  • 745
  • 5
  • 16
0

The easiest way is not make that field disabled(not editable) and populate with current date.. So you don't need a validation.

If you don't like this approach create an annotation of your own refer this url
Annotation for hibernate validator for a date at least 24 hours in the future

Instead of 24 hour check, you need to check whether date value is equal to current date

Community
  • 1
  • 1
Jobin
  • 5,610
  • 5
  • 38
  • 53