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 acontext: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!