2

So, I makes this enum in one of my Hibernate objects in lieu of creating a LUT in the DB:

@Entity
@Table(name = "Foo", schema = "dbo")
public class Foo 
{
    private static final long serialVersionUID = 2L;

    int idFoo;
    String name;
    String type;

    public Foo() 
    {
    }

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "idFoo", unique = true, nullable = false)
    public int getID() { return idFoo; }    
    public void setID(int idFoo) { this.idFoo = idFoo; }

    @Column(name="name", nullable=false, length=50)
    public String getName() { return this.name; }
    public void setName(String aString) { this.name = aString; }

    @Column(name="type", nullable=false, length=8)
    public String getType() { return this.type; }
    public void setType(String aString) { this.type = aString; }

    public static enum FooType
    {
        First,
        Middle,
        Last;

        public boolean isLast() { return this == Last; }
    }
}

And for the life of me I could not get Spring to like it. No matter what I did, I got the following error message:

Caused by: java.lang.NoSuchMethodException: com.bar.orm.FooType.<init>()
        at java.lang.Class.getConstructor0(Class.java:2810) [rt.jar:1.7.0_45]
        at java.lang.Class.getDeclaredConstructor(Class.java:2053) [rt.jar:1.7.0_45]
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:67) [org.springframework.beans-3
.1.1.RELEASE.jar:3.1.1.RELEASE]
        ... 23 more

In the example, the first line would have cited Foo.$1, not the named enum.

Things I tried:

  • remove static from declaration
  • give it a constructor (can't be public, but Spring can see package private via reflection)
  • move it to a separate class file
  • change it to static final strings and move to JDK 1.7 to use switch(String)

Only the last one worked. It really sucks that Spring restricts me from using a pretty cool part of the Java language. But it's probably not Spring's fault, is it? What did I do wrong? How can I have written the enum above so that Spring would have either left it alone or let me use it?

Edit:

Currently, the working solution consists of the following:

  • Each enum is in its own class file rather than being an inner class of the object that persists its values. (There are valid design principles for both approaches but all-in-all, largely equivalent in weight.)
  • The enum is added to a context:component-scan in a context:exclude-filter tag with a regex that pretty much equates to the class name. All other enums are in packages that are also excluded.
  • When the enum is used in a switch statement, javac creates a special class for it using the inner class naming scheme (more info). Since the switch uses the enum, that generated class also has to be added to the exclusion filter: "MyClass.1", etc.

I'm editing the question because I still cannot believe this isn't a result of inexperience with Spring (that last ridiculous requirement just tipped the boat!), still hoping for an answer that shows the "right" way to let Spring do the right thing with this core language feature!

Community
  • 1
  • 1
user1944491
  • 559
  • 1
  • 8
  • 24
  • Please post the full stack trace. – Sotirios Delimanolis Jul 09 '15 at 22:40
  • @SotiriosDelimanolis The full stack trace is huge; the snippet above is the last 'Caused by' section. I will reproduce and post however. (Is there a way to expand the _"23 more"_ parts?) – user1944491 Jul 10 '15 at 13:08
  • Ah, here's an explanation of _23 more_: http://stackoverflow.com/questions/7597797/how-to-show-full-stack-trace-on-eclipse – user1944491 Jul 10 '15 at 13:16
  • Doesn't matter if it's huge, If you post it as cod (wrap with the `{}` button in edit mode), Stack Overflow will add scrolling to it. – Sotirios Delimanolis Jul 10 '15 at 19:57
  • OK, I've decided that the full stack trace is immaterial - the excerpt I provided is Spring's fundamental issue. If you want to reproduce, simply create an enum with a method - my guess is that Spring is unable to handle this language feature. – user1944491 Jul 27 '15 at 19:49
  • I wanted to see the stack trace to see what component tries to instantiate `FooType`. It doesn't seem like Hibernate is involved right now. You shouldn't be instantiating `enum` types. They provide constants for a reason. Nested `enum` types are `static` implicitly. The `static` keyword is redundant in that case. – Sotirios Delimanolis Jul 27 '15 at 21:04
  • @SotiriosDelimanolis, that's a good point. I made progress by adding the enum to the "excludes" list in the XML config and then had also to add the class that takes this enum in its constructor!! So, the solution turns out to be "Spring can't handle enums so keep them out of its way". Which is unfortunate. And you're right, it was not a Hibernate issue, but Spring issue. Many thanks! – user1944491 Jul 28 '15 at 10:34

1 Answers1

2

I would move the enum to its own file so that you can access it other places without specifying your class.

public enum FooType{
    First,
    Middle,
    Last
}

add @Enumerated(EnumType.STRING) to your use of the enum

@Enumerated(EnumType.STRING)
private FooType type;
penguin
  • 724
  • 5
  • 11