Class CastException ContainerEventProvider$ContainerCalendarEvent

I’m trying to use Vaadin Calendar along with JPAcontainer for backend persistence.

I can add events to the Calendar / database just fine using the example in the Book of Vaadin Examples (http://demo.vaadin.com/book-examples/book/#calendar.jpacontainer)

The Calendar compenent then displays the “event” however it does not get the styleName.

My model lookes like this:


@Entity
@Table(name = "reservation")
public class Reservation {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
    
	private String caption;
	
	private String description;
    
    @Temporal(TemporalType.TIMESTAMP)
    private Date startDate;

    @Temporal(TemporalType.TIMESTAMP)
    private Date endDate;
    
    private String styleName;
	
    @NotNull
	@ManyToOne(targetEntity=Principal.class)
    @JoinColumn(name="principal_id")
    private Principal principal;
    
    public Reservation(){}
    
    public Reservation(String caption, String description, Date startDate, Date endDate, Principal principal){
    	this.caption = caption;
        this.description = description;
        this.startDate = startDate;
        this.endDate = endDate;
        this.principal = principal;
        this.styleName = principal.getSchedule().getStyleName();
    }

	... getters / setters

}

@Entity
@Table(name = "principal")
@Cacheable
@Cache(	type=CacheType.SOFT, // Cache everything until the JVM decides memory is low.
	expiry=36000000  // 10 minutes
)
public class Principal {

	@Transient
	private static final long serialVersionUID = -7036533579059851799L;
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	@NotNull
	private String firstName;
	
	@NotNull
	private String lastName;
	
	@Transient
	private String fullName;
	
	@NotNull
	@Column(unique = true)
	private String emailAddress;
	
	@NotNull
	@Column(unique = true)
	private String telephoneNumber;
	
	@NotNull
	@Enumerated(EnumType.STRING)
	private Schedule schedule;
	
	@OneToMany(mappedBy="principal", targetEntity=Reservation.class, cascade = CascadeType.ALL, fetch=FetchType.EAGER)
	private Set<Reservation> reservations;

	... getters / setters.
}

public class ReservationEvent extends BasicEvent implements Cloneable {

	private static final long serialVersionUID = -567658372451936210L;

	private Principal principal;

	public Principal getPrincipal() {
		return principal;
	}

	public void setPrincipal(Principal principal) {
		this.principal = principal;
		fireEventChange();
	}
	
	@Override
    public ReservationEvent clone() throws CloneNotSupportedException {
        return (ReservationEvent) super.clone();
    }
	
    @Override
	public String getStyleName() {
		return principal.getSchedule().getStyleName();
	}

	@Override
    public String toString() {
        return getTime() + ": " + getCaption();
    }

    public String getTime() {
        DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
        String time = formatter.format(getStart()) + "-" + formatter.format(getEnd());
        return time;
    }
}

And my ContainerEventProvider like this:


dataSource = new ContainerEventProvider(reservations){
	private static final long serialVersionUID = 1886232671138854087L;
	@Override
        public void addEvent(CalendarEvent event) {
		try{
			ReservationEvent re = (ReservationEvent) event;
			re.setCaption(re.getPrincipal().getSchedule().getCaption()+" "+re.getPrincipal().getFirstName()+" "+re.getPrincipal().getLastName());
			re.setStyleName(re.getPrincipal().getSchedule().getStyleName());
			String desc = re.getDescription() != null ? re.getDescription():"No description";
			Reservation entity = new Reservation(re.getCaption(), desc, re.getStart(), re.getEnd(), re.getPrincipal());
			reservations.addEntity(entity);
		}catch(Exception e){
			e.printStackTrace();
		}
        }
			
};
dataSource.setStartDateProperty("startDate");
dataSource.setEndDateProperty("endDate");

Selecting the event in the calendar returns a ContainerEventProvider$ContainerCalendarEvent but I need to cast it to my ReservationEvent class but get:

java.lang.ClassCastException: com.vaadin.addon.calendar.ui.ContainerEventProvider$ContainerCalendarEvent cannot be cast to com…vaadin.components.ReservationEvent

Can anyone help me out here using Vaadin Calendar with JPAcontainer to fully manage “custom” events? The Book example only demontrates adding events!

Thanks in advance
SketchCND

Is there some reason why you are not adding the JPAContainer directly to the Calendar but instead wrapping it in your own ContainerEventProvider?

If not the simple solution would be something along these lines:

// Get your hands on the JPAContainer, here  I am creating one
JPAContainer<Reservation> eventContainer = JPAContainerFactory.make(Reservation.class, PERSISTANCE_UNIT);
  
// Attach the JPAContainer to the Calendar
calendar.setContainerDataSource(eventContainer);

The Reservation entity will need to implement the
CalendarEventEditor
(and optionally the
EventChangeNotifier
) interface for that to work (which you basically already have done, the “implements CalendarEventEditor”- statement is just missing).

John, I’m not sure this answers the question. I am also using a JPAContainer to persist custom Calendar Events to a database. I use a ContainerEventProvider so that when a new event is added to the calender it creates a new custom Calendar Event and persists it to the database. This work fine, but I also want to be able to modify existing events by using my own EventClickHandler. When the eventClick which is passed into this handler however will not cast to my custom Calendar Event.

Here are the snippets of my code.


                final JPAContainer<Appointment> container =
		JPAContainerFactory.make(Appointment.class, entityManagerFactory.createEntityManager());
		
		// Customize the event provider for adding events as entities
		ContainerEventProvider cep =
			new ContainerEventProvider(container) 
			{
				@Override
				public void addEvent(CalendarEvent event) 
				{
					Appointment entity = new Appointment(
						employee,
						event.getCaption(), event.getDescription(),
						event.getStart(), event.getEnd(),
						event.getStyleName());
					
					System.out.println("test");
					container.addEntity(entity);					
				}
			};
		
		// Set the container as the data source
		myCalendar = new Calendar();	
		myCalendar.setEventProvider(cep);

                myCalendar.setHandler(new BasicEventClickHandler()
			{
				public void eventClick(EventClick event) 
				{
					Appointment appointment = (Appointment) event.getCalendarEvent();
                                  //	BasicEvent appointment = (BasicEvent) event.getCalendarEvent();
					getWindow().showNotification("Event clicked: " + appointment.getCaption(), appointment.getDescription());
				}
			});

Appointment Class (the Custom Calendar Event)


@Entity
@SuppressWarnings("serial")
public class Appointment extends BasicEvent implements Serializable, CalendarEventEditor, EventChangeNotifier 
{
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
...
getters, setters etc.
}

When I cast the EventClick.getCalendarEvent to BasicEvent (currently commented out) it works, but I have no way of accessing the custom event fields. When I try to cast it to the Appointment object, it throws a ClassCastException.

Any Help is really appreciated.
Thanks

Hello
I am facing the same problem.
Have you resolved your concern, and if so can you share the solution please?
Thanks
MK