1

I am using a Comparator to sort a List<Entity> by it's property (of type Date) in viewscoped managed bean.

The problem is that I keep getting the ClassCastException as follows -

java.lang.ClassCastException: pkg.db.BaseArStatus cannot be cast to pkg.db.BaseArStatus.

Why is it not able to cast BaseArStatus to BaseArStatus? Is it because BaseArStatus is an Entity?

The problem is really strange to me because I am not getting the exception every time. Most of the it works fine (runs without any problem) when build and deploy the application but sometimes (even though I am doing the same thing - build and deploy) it fails at runtime with the ClassCastException.

Why is this happening only sometimes and not all the time? Is it because I am using it in managed bean?

This is how the managed bean looks like -

@ManagedBean
@ViewScoped
public class MyBean {

@PersistenceContext(unitName = "myPU")
private EntityManager em;

public void myMethod() {
    List<BaseArStatus> basList = this.fetchAllBaseArStatus();
    Collections.sort(basList, new Comparator<BaseArStatus>() {
        @Override
        public int compare(BaseArStatus o1, BaseArStatus o2) {
            return o1.getMonthDate().compareTo(o2.getMonthDate());
        }
    });
//...

And the entity BaseArStatus -

@Entity
@Table(name = "base_ar_status")
@NamedQueries({
    @NamedQuery(name = "BaseArStatus.findAll", query = "SELECT b FROM BaseArStatus b")})
public class BaseArStatus implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @NotNull
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @NotNull
    @Column(name = "month_date")
    @Temporal(TemporalType.DATE)
    private Date monthDate;
    @Basic(optional = false)
    @NotNull
    @Column(name = "ar_count")
    private double arCount;
    @Size(max = 50)
    @Column(name = "user_id")
    private String userId;
    @Column(name = "last_update_date")
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastUpdateDate;

    public BaseArStatus() { }
//...
Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
  • I wonder if there are multiple ClassLoaders involved... – NPE Sep 23 '11 at 19:05
  • Possible duplicate of http://stackoverflow.com/questions/2371967/java-getting-class-cast-exception-where-both-classes-are-exactly-the-same – Ed Staub Sep 23 '11 at 19:09
  • possible duplicate of [ClassCastException error when casting back to original class](http://stackoverflow.com/questions/7432410/classcastexception-error-when-casting-back-to-original-class) – Robin Sep 23 '11 at 19:12
  • It might help if you provided some extra context around your problem. Is your application deployed to a servlet container? – frankjl Sep 23 '11 at 19:14
  • @frankjl: It's a web application. Deployed in the Glassfish 3.1. – Bhesh Gurung Sep 23 '11 at 19:16
  • To exclude one and other, is it a WAR or EAR? – BalusC Sep 23 '11 at 19:23
  • What IDE/buildtool are you using to create WAR? Where did the entity class originate? In the web project which will thus end up in `/WEB-INF/classes` of the generated WAR, or in a separate JPA project which will thus end up as JAR in `/WEB-INF/lib` of the generated WAR? – BalusC Sep 23 '11 at 19:36
  • @BalusC: I am using Netbeans7 (Ant). It's Web application with no other projects as JPA. `/WEB-INF/classes` is where the enitity class is at. – Bhesh Gurung Sep 23 '11 at 19:41
  • Does this happen when you run outside of NetBeans? – Ed Staub Sep 23 '11 at 19:45
  • @Ed Staub: I haven't tried it outside of NetBeans but It does not happen every time I deploy the application from Netbeans. Sometimes I have to do clean build before deploy. – Bhesh Gurung Sep 23 '11 at 19:47
  • Hopefully, someone else with NetBeans experience can confirm/deny this theory, or fill in the blanks. I'm picturing a situation where you've run Ant, have deployed, and then are trying to run within the IDE, where it's supplying a second copy of the .class file. If no one chimes in and this makes any sense at all, try removing the .class file from WEB-INF/classes. – Ed Staub Sep 23 '11 at 19:51

2 Answers2

5

Two different classloaders are loading two different copies of the class. When client code "familiar" with one copy of the class gets an object that's an instance of the other copy of the class, this is what you get.

The problem will only occur if the class has been loaded by both classloaders. This can make it seem intermittent; depending on events you often have no control over, one of the classloaders may or may not have loaded the class. In my experience, this is a problem most commonly seen in Java EE programming, which, of course, is what you're doing.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Ed Staub
  • 15,480
  • 3
  • 61
  • 91
  • Is there any way to solve to this two different ClassLoaders problem? – Bhesh Gurung Sep 23 '11 at 19:15
  • The problem isn't two different classloaders - it's two different copies of BaseArStatus.class. Consider where the BaseArStatus instance came from. It's probably coming from a web app that has its own copy of the jar it's defined in - possibly even a different version of the jar. – Ed Staub Sep 23 '11 at 19:26
  • If nothing else works, look across the deployment for multiple copies of the .class file (including in wars, ears, jars). This will give you a clue. – Ed Staub Sep 23 '11 at 19:40
  • For right now the problem is gone. I have repeated the same process for 10 different entities. And have deployed the WAR after I am done with each entity and have had that problem with like about 4 of them. I still have to repeat the same process for 10 more entities and I am pretty sure I will get that exception again at that time I will check that WAR file. – Bhesh Gurung Sep 23 '11 at 19:46
  • Did you restart your server after deploying? If not, that's "the problem" - the server had a hot old copy of the .class in memory. This is an unfortunate part of JEE programming. Sometimes you need to restart, sometimes you don't. – Ed Staub Sep 23 '11 at 19:56
  • You were right. I redeployed the application from Netbeans again and tried to run it with server restart and I got the exception. And then I restarted server and ran the application and it ran without any problem. Thanks for the suggestion, helped find out the cause of the problem. – Bhesh Gurung Sep 23 '11 at 20:28
0

Definitely sounds like a comparison between classes loaded by different ClassLoaders. You can use the Class.getClassLoader() method to confirm on deny this for us. Catch the Exception and print whether or not classA.getClassLoader() == classB.getClassLoader().

Eric Lindauer
  • 1,813
  • 13
  • 19