I am considering moving from Hibernate to jOOQ but I can't find e.g.
how to have Pattern-Constraints on a String like this in Hibernate:
#NotEmpty(message = "Firstname cannot be empty")
#Pattern(regexp = "^[a-zA-Z0-9_]*$", message = "First Name can only contain characters.")
private String firstname;
How would I do that in jOOQ?
The "jOOQ way"
The "jOOQ way" to do such validation would be to create either:
A CHECK constraint in the database.
A trigger in the database.
A domain in the database.
After all, if you want to ensure data integrity, the database is where such constraints and integrity checks belong (possibly in addition to functionally equivalent client-side validation). Imagine a batch job, a Perl script, or even a JDBC statement that bypasses JSR-303 validation. You'll find yourself with corrupt data in no time.
If you do want to implement client-side validation, you can still use JSR-303 on your DTOs, which interact with your UI, for instance. But you will have to perform validation before passing the data to jOOQ for storage (as artbristol explained).
Using a Converter
You could, however, use your own custom type by declaring a Converter on individual columns and by registering such Converter with the source code generator.
Essentially, a Converter is:
public interface Converter<T, U> extends Serializable {
U from(T databaseObject);
T to(U userObject);
Class<T> fromType();
Class<U> toType();
}
In your case, you could implement your annotations as such:
public class NotEmptyAlphaNumericValidator implements Converter<String, String> {
// Validation
public String to(String userObject) {
assertNotEmpty(userObject);
assertMatches(userObject, "^[a-zA-Z0-9_]*$");
return userObject;
}
// Boilerplate
public String from(String databaseObject) { return databaseObject; }
public Class<String> fromType() { return String.class; }
public Class<String> toType() { return String.class; }
}
Note that this is more of a workaround, as Converter hasn't been designed for this use-case, even if it can perfectly implement it.
Using formal client-side validation
There's also a pending feature request #4543 to add more support for client-side validation. As of jOOQ 3.7, this is not yet implemented.
I recommend you don't try to use jOOQ in a 'hibernate/JPA' way. Leave the jOOQ generated classes as they are and map to your own domain classes manually, which you are free to annotate however you like. You can then call a JSR validator before you attempt to persist them.
For example, jOOQ might generate the following class
public class BookRecord extends UpdatableRecordImpl<BookRecord> {
private String firstname;
public void setId(Integer value) { /* ... */ }
public Integer getId() { /* ... */ }
}
You can create your own domain object
public class Book {
#NotEmpty(message = "Firstname cannot be empty")
#Pattern(regexp = "^[a-zA-Z0-9_]*$", message = "First Name can only contain characters.")
private String firstname;
public void setId(Integer value) { /* ... */ }
public Integer getId() { /* ... */ }
}
and map by hand once you've retrieved a BookRecord, in your DAO layer
Book book = new Book();
book.setId(bookRecord.getId());
book.setFirstname(bookRecord.getFirstname());
This seems quite tedious (and ORM tries to spare you this tedium) but actually it scales quite well to complicated domain objects, in my opinion, and it's always easy to figure out the flow of data in your application.
Related
I'm having trouble converting between java.sql.Timestamp and java.time.Instant using JOOQ converters.
Here's a simplified version of the code I'm working with.
public class User {
private static final Converter<Timestamp, Instant> MY_CONVERTER= Converter.of(
Timestamp.class,
Instant.class,
t -> t == null ? null : t.toInstant(),
i -> i == null ? null : Timestamp.from(i)
)
public static Table<?> table = DSL.table("user");
public static Field<String> name = DSL.field(DSL.name(table.getName(), "name"), String.class);
public static Field<Instant> name = DSL.field(DSL.name(table.getCreated(), "created"), SQLDataType.TIMESTAMP.asConvertedDataType(Converter.of(MY_CONVERTER)));
}
private class UserDto {
private String name;
private Instant created;
// getters, setters, etc.
}
public class UserWriter {
// constructor with injected DefaultDSLContext etc..
public void create(UserDto user) {
dslContext.insertInto(User.table, User.firstName, User.lastName)
.values(user.getName(), user.getCreated())
.execute();
}
}
public class UserReader {
// constructor with injected DefaultDSLContext etc..
public Result<Record> getAll() {
return dslContext.select().from(User.table).fetch();
}
}
public class UserService {
// constructor with injected UserReader etc..
public Collection<UserDto> getAll() {
return userReader
.getAll()
.stream()
.map(Users::from)
.collect(Collectors.toList());
}
}
public class Users {
public static UserDto from(Record record) {
UserDto user = new UserDto();
user.setName(record.get(User.name));
user.setCreated(record.get(User.created);
return user;
}
}
When I create a new User the converter is called and the insertion works fine. However, when I select the Users the converter isn't called and the record.get(User.created) call in the Users::from method returns a Timestamp (and therefore fails as UserDto.setCreated expects an Instant).
Any ideas?
Thanks!
Why the converter isn't applied
From the way you phrased your question (you didn't post the exact SELECT statement that you've tried), I'm assuming you didn't pass all the column expressions explicitly. But then, how would jOOQ be able to find out what columns your table has? You declared some column expressions in some class, but that class isn't following any structure known to jOOQ. The only way to get jOOQ to fetch all known columns is to make them known to jOOQ, using code generation (see below).
You could, of course,let User extend the internal org.jooq.impl.TableImpl class and use internal API to register the Field values. But why do that manually, if you can generate this code?
Code generation
I'll repeat the main point of my previous question, which is: Please use the code generator. I've now written an entire article on why you should do this. Once jOOQ knows all of your meta data via code generation, you can just automatically select all columns like this:
UserRecord user = ctx
.selectFrom(USER)
.where(USER.ID.eq(...))
.fetchOne();
Not just that, you can also configure your data types as INSTANT using a <forcedType>, so you don't need to worry about data type conversion every time.
I cannot stress this enough, and I'm frequently surprised how many projects try to use jOOQ without code generation, which removes so much of jOOQ's power. The main reason to not use code generation is if your schema is dynamic, but since you have that User class, it obviously isn't dynamic.
Is there some way in Spring Boot that I can perform validation on properties that depend on each other's values, and have the error message be associated with the property?
I want to return the errors to the user in a nice JSON structure:
{
"errors": {
"name": "is required if flag is true"
}
}
Example:
#Entity
public class MyEntity {
private boolean nameRequiredFlag;
// Required if "nameRequiredFlag" is set to true:
private String name;
}
One solution that doesn't solve my problem of associating the error message with the name property is to create a validator annotation for the entity:
#ValidEntity
public class MyEntity {
private boolean nameRequiredFlag;
// Required if "nameRequiredFlag" is set to true:
private String name;
}
#Constraint( validatedBy = { MyEntityValidator.class } )
#Documented
#Target( { ElementType.TYPE } )
#Retention( RetentionPolicy.RUNTIME )
public #interface ValidEntity{
Class<?>[] groups () default {};
String message () default "name is required if 'nameRequiredFlag' is true";
Class<? extends Payload>[] payload () default {};
}
public class MyEntityValidator implements Validator<ValidEntity, MyEntity> {
#Override
public boolean isValid ( MyEntity entity, ConstraintValidatorContext context ) {
if ( !entity.nameRequiredFlag ) return true;
return !StringUtils.isBlank( entity.getName() );
}
}
This is laughably cumbersome and doesn't solve my problem. Isn't there any way I can do this with the framework validation?
Edit: This is for a JSON API, and the consumer really needs to be able to associate the error message to a best guess at which field has an issue. It is not helpful to send the consumer an error message for the whole object, or a computed property.
Solution given by #EvicKhaosKat is one way of doing it. However, when there are too many fields dependent on each other in a complicated way, your class becomes full of annotations and I personally struggle a lot relating them.
A simpler approach is to create a method(s) in your pojo which does the cross field validations and returns a boolean. On the top of this method annotate it with #AssertTrue(message = "your message"). It will solve your problem in a cleaner fashion.
public class SampleClass {
private String duration;
private String week;
private String month;
#AssertTrue(message = "Duration and time attributes are not properly populated")
public boolean isDurationCorrect() {
if (this.duration.equalsIgnoreCase("month")) {
if (Arrays.asList("jan", "feb", "mar").contains(month))
return true;
}
if (this.duration.equalsIgnoreCase("week")) {
if (Arrays.asList("1-7", "8-15", "16-24", "25-31").contains(week))
return true;
}
return false;
}
}
Note: I have not tested this code but have used this approach in multiple places and it works.
Possible reason is that name validation operates on not-yet-fully constructed object, so nameRequiredFlag is not filled yet.
As an option there is a #GroupSequence annotation, which allows to group and perform validations in an order you specify.
For example it is possible to add to MyEntity annotations:
#ValidEntity(groups = DependentValidations.class)
#GroupSequence({MyEntity.class, DependentValidations.class})
So all the other validation annotations on MyEntity class gonna be performed first, and after that DependentValidations group, which consists of ValidEntity.
Thus ValidEntity will be called on fully created object, and the last in order.
(DependentValidations.class - just an empty interface created somewhere nearby, like any other marker interface)
https://www.baeldung.com/javax-validation-groups will possibly describe that in much more details.
p.s. answer provided by #Innovationchef will possibly suit the case more :)
I know this is a common question, but I haven't found another that solves my doubts.
Usually, if the project is small, I've persistence annotations in the same object that represents the domain object. This allows to load the entity from database and keep all the setters private, ensuring any instance is always in a valid state. Something like:
#Entity
class SomeEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String attribute1;
private String attribute2;
private String attribute3;
// ... other attributes
protected SomeEntity() {}
/* Public getters */
public Long getId() { ... }
public String getAttribute1() { ... }
public String getAttribute2() { ... }
/* Expose some behaviour */
public void updateAttributes(String attribute1, String attribute2) {
/* do some validations before updating */
}
}
My problem appears if I want to hava a different persistent model. Then I would have something like:
/* SomeEntity without persistent info */
class SomeEntity {
private Long id;
private String attribute1;
private String attribute2;
private String attribute3;
// ... other attributes
protected SomeEntity() {}
/* Public getters */
public Long getId() { ... }
public String getAttribute1() { ... }
public String getAttribute2() { ... }
/* Expose some behaviour */
public void updateAttributes(String attribute1, String attribute2) {
/* do some validations before updating */
}
}
and DAO:
#Entity
class SomeEntityDAO {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String attribute1;
private String attribute2;
private String attribute3;
public SomeEntityDAO() {}
/* All getters and setters */
}
My question is, how can I map SomeEntityDAO to SomeEntity without exposing SomeEntity's attributes?
If I create a constructor like: public SomeEntity(String attribute1, String attribute2, ...) {}, then anyone can create an invalid instance of SomeEntity. The same occurs if I make all setters public in SomeEntity.
I also don't think is a valid solution build the object using updateAttributes() since this will execute some validations I don't whant to execute at this point (we trust the data that's persistet in database).
I'm thinking in having all the setters protected, so the DAO can extend the Entity and have access to setters... but I'm not sure if this is a good option.
Which is the best or common approach to solve this problem?
I've had the same kind of problem. And looking around I've found no solution. Believe me, if it exists is well hidden somewhere. None that suggests what to do when you have to deal with an old project where ORM entities are everywhere and there's a big step between Domain and ORM model.
Given this, I've deducted that if you really want to keep your Domain entities pure (so non get and set - the latter I would NEVER accept!) you have to do some deals. Because there's no way to share the internals without giving the entities some extra knowledge. Beware, this doesn't mean that you have to make the Domain entities aware of the ORM layer, nor that you have to use getters. Just, what I've concluded, the Domain entities should have ways to expose them as a different model.
So, in conclusion, what I would do in your situation is to build up a Visitor pattern. The Domain entity EntityA would implement the EntityAVisitable interface to accept a EntityAVisitor or something like this.
interface EntityAVisitable {
accepts(EntityAVisitor visitor);
}
The builder implements the interface required by the Visitor, EntityAVisitor.
interface EntityAVisitor<T>{
setCombinedValue1_2(String attribute1_attribute2_combinedInEntity);
<T> build();
}
The build() function of the interface EntityAVisitor uses a generic type T. In this way the Domain entity is agnostic about the return type of the concrete implementation of the EntityAVisitor.
Is it perfect? No.
Perfect solution would be to get rid of the ORM (actually I would say that I hate them, because the way are used is most of the times wrong - but this is my personal thought).
Is it nice? No.
A nice solution is not allowed due to language restrictions (I suppose you use Java).
Does it a good work in encapsulating the real content of your Domain entity? Yes.
Not only, in this way you can decide exactly what could be exposed and how. So, in my opinion, is a good deal between keeping the entity pure and having to work with an ORM under the seat.
Domain entity should be self-validating meaning it should only validate itself based on it's internal values. If update requires validation that depends on external dependencies, then I would create an updater class that is responsible for the update. From the updater class, you can use specification pattern (as an injectable dependency) to implement the validation.
Use domain entities when modifying, and DTOs for read-only projections. There are performance and simplification gains when you use straight DTOs in read-only. This is used in CQRS patterns.
class SomeEntity {
private Long id;
private String attribute1;
private String attribute2;
private String attribute3;
// ... other attributes
public SomeEntity() {}
/* Public getters/setter */
public Long getId() { ... }
public String getAttribute1() { ... }
public String getAttribute2() { ... }
public Long setId() { ... }
public String setAttribute1() { ... }
public String setAttribute2() { ... }
}
//classes/interfaces named for clarity
class EntityUpdater implements IEntityUpdater {
public EntityUpdater (ISpecification spec){
}
public updateEntity(SomeEntity entity){
//assert/execute validation
}
}
Some ORMs allow setting entity values through field access (as opposed to setter methods).
JPA uses the #Access annotation. See What is the purpose of AccessType.FIELD, AccessType.PROPERTY and #Access
I created an ORM, sormula, that can use field access. See #Row fieldAccess and test case org.sormula.tests.fieldaccess.
Consider the following pojo for reference:
public class User{
private String username;
private String firstName;
private String middleName;
private String lastName;
private String phone;
//getters and setters
}
My application is a basically spring-boot based REST API which exposes two endpoints, one to create the user and the other to retrieve a user.
The "users" fall into certain categories, group-a, group-b etc. which I get from the headers of the post request.
I need to validated the user data in runtime and the validations may differ based on the group of a user.
for example, the users that fall into group-a may have phone numbers as an optional field whereas it might be a mandatory field for some other group.
The regex may also vary based on their groups.
I need to be able to configure spring, to somehow dynamically validate my pojo as soon as they are created and their respective set of validations get triggered based on their groups.
Maybe I can create a yml/xml configuration which would allow me to enable this?
I would prefer to not annotate my private String phone with #NotNull and #Pattern.
My configuration is as follows:
public class NotNullValidator implements Validator {
private String group;
private Object target;
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
#Override
public void validate(Object o) {
if (Objects.nonNull(o)) {
throw new RuntimeException("Target is null");
}
}
}
public interface Validator {
void validate(Object o);
}
#ConfigurationProperties(prefix = "not-null")
#Component
public class NotNullValidators {
List<NotNullValidator> validators;
public List<NotNullValidator> getValidators() {
return validators;
}
public void setValidators(List<NotNullValidator> validators) {
this.validators = validators;
}
}
application.yml
not-null:
validators:
-
group: group-a
target: user.username
-
group: group-b
target: user.phone
I want to configure my application to somehow allow the validators to pick their targets (the actual objects, not the strings mentioned in the yml), and invoke their respective public void validate(Object o) on their targets.
P.S.
Please feel free to edit the question to make it better.
I am using jackson for serializing and deserializing JSON.
The easiest solution to your problem, as i see it, is not with Spring or the POJOs themselves but with a design pattern.
The problem you're describing is easily solved by a strategy pattern solution.
You match the strategy to use by the header you're expecting in the request, that describes the type of user, and then you perform said validations inside the strategy itself.
This will allow you to use the same POJO for the whole approach, and deal with the specifics of handling/parsing and validating data according to the each type of user's strategy.
Here's a link from wiki books with a detailed explanation of the pattern
Strategy Pattern
Suppose you have a basic interface for your strategies:
interface Strategy {
boolean validate(User user);
}
And you have 2 different implementations for the 2 different types of user:
public class StrategyA implements Strategy {
public boolean validate(User user){
return user.getUsername().isEmpty();
}
}
public class StrategyB implements Strategy {
public boolean validate(User user){
return user.getPhone().isEmpty();
}
}
You add a Strategy attribute to your User POJO and assign the right implementation of the Strategy to that attribute when you receive the post request.
Everytime you need to validate data for that user you just have to invoke the validate method of the assigned strategy.
If each User can fit multiple strategies, you can add a List<Strategy> as an attribute instead of a single one.
If you don't want to change the POJO you have to check which is the correct strategy every time you receive a post request.
Besides the validate method you can add methods to handle data, specific to each strategy.
Hope this helps.
You can use validation groups to control which type of user which field gets validated for. For example:
#NotBlank(groups = {GroupB.class})
private String phone;
#NotBlank(groups = {GroupA.class, GroupB.class})
private String username;
Then you use the headers from the request that you mentioned to decide which group to validate against.
See http://blog.codeleak.pl/2014/08/validation-groups-in-spring-mvc.html?m=1 for a complete example.
Updated to include a more comprehensive example:
public class Val {
private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public boolean isValid(User user, String userType) {
usergroups userGroup = usergroups.valueOf(userType);
Set<ConstraintViolation<User>> constraintViolations = validator.validate(user, userGroup.getValidationClass());
return constraintViolations.isEmpty();
}
public interface GroupA {}
public interface GroupB {}
public enum usergroups {
a(GroupA.class),
b(GroupB.class);
private final Class clazz;
usergroups(Class clazz) {
this.clazz = clazz;
}
public Class getValidationClass() {
return clazz;
}
}
}
This doesn't use application.yaml, instead the mapping of which fields are validated for each group is set in annotations, similar results using Spring's built in validation support.
I was able to solve my problem with the use of Jayway JsonPath.
My solution goes as follows:
Add a filter to your API which has the capability to cache the InputStream of the ServletRequest since it can be read only once. To achieve this, follow this link.
Create a bunch of validators and configure them in your application.yml file with the help of #ConfigurationProperties. To achieve this, follow this link
Create a wrapper which would contain all your validators as a list and initialize it with #ConfigurationProperties and the following configuration:
validators:
regexValidators:
-
target: $.userProfile.lastName
pattern: '[A-Za-z]{0,12}'
group: group-b
minMaxValidators:
-
target: $.userProfile.age
min: 18
max: 50
group: group-b
Call the validate method in this wrapper with the group which comes in the header, and then call the validate of the individual validators. To achieve this, I wrote the following piece of code in my wrapper:
public void validate(String input, String group) {
regexValidators.stream()
.filter(validator -> group.equals(validator.getGroup()))
.forEach(validator -> validator.validate(input));
minMaxValidators.stream()
.filter(validator -> group.equals(validator.getGroup()))
.forEach(validator -> validator.validate(input));
}
and the following method in my validator:
public void validate(String input) {
String data = JsonPath.parse(input).read(target);
if (data == null) {
throw new ValidationException("Target: " + target + " is NULL");
}
Matcher matcher = rule.matcher(data);
if (!matcher.matches()) {
throw new ValidationException("Target: " + target + " does not match the pattern: " + pattern);
}
}
I have created a functioning project to demonstrate the validations and it can be found here.
I understand that the answer alone might not be very clear, please follow the above mentioned url for the complete source code.
I'm migrating a legacy system over to use Hibernate 3. It currently generates its own identifiers. To keep with what the system currently does before I try and move it over to something a little better, how would I go about specifying (using annotations) my own class that will return the custom generated identifiers when an insert occurs?
Something like:
#Id
#CustomIdGenerator(Foo.class) // obviously this is not a real annotation
public String getId() { ... }
Where the Foo class has one method that generates the identifier.
Currently I'm just calling the setId(String id) method manually but was hoping for a better way to deal with this situation.
I don't think there is out-of-box support for generating custom Ids using custom annotations using pure JPA-2 API. But if you want to use provider specific API, then the job is pretty simple. Sample Example
To be provider independent try any of following tricks....
IdGeneratorHolder
public abstract class IdGeneratorHolder {
/* PersistentEntity is a marker interface */
public static IdGenerator getIdGenerator(Class<? extends PersistentEntity> entityType) {
/* sample impelementation */
if(Product.class.isAssignableFrom(entityType)) {
return new ProductIdGenerator();
}
return null;
}
}
General IdGenerator interface
public interface IdGenerator {
String generate();
}
Specific IdGenerator - Product Id Generator
public class ProductIdGenerator implements IdGenerator {
public String generate() {
/* some complicated logic goes here */
return ${generatedId};
}
}
Now set the generated id either in no-arg constructor OR in #PrePersist method.
Product.java
public class Product implements PersistentEntity {
private String id;
public Product() {
id = IdGeneratorHolder.getIdGenerator(getClass()).generate();
}
#PrePersist
public void generateId() {
id = IdGeneratorHolder.getIdGenerator(getClass()).generate();
}
}
In above example all the ids are of the same type i.e. java.lang.String. If the persistent entities have ids of different types.....
IdGenerator.java
public interface IdGenerator {
CustomId generate();
}
CustomId.java
public class CustomId {
private Object id;
public CustomId(Object id) {
this.id = id;
}
public String toString() {
return id.toString();
}
public Long toLong() {
return Long.valueOf(id.toString());
}
}
Item.java
#PrePersist
public void generateId() {
id = IdGeneratorHolder.getIdGenerator(getClass()).generate().toLong();
}
You can also use your custom annotation...
CustomIdGenerator.java
public #interface CustomIdGenerator {
IdStrategy strategy();
}
IdStrategy.java
enum IdStrategy {
uuid, humanReadable,
}
IdGeneratorHolder.java
public abstract class IdGeneratorHolder {
public static IdGenerator getIdGenerator(Class<? extends PersistentEntity> entityType) {
try { // again sample implementation
Method method = entityType.getMethod("idMethod");
CustomIdGenerator gen = method.getAnnotation(CustomIdGenerator.class);
IdStrategy strategy = gen.strategy();
return new ProductIdGenerator(strategy);
}
One more thing.... If we set id in #PrePersist method, the equals() method cannot rely on id field (i.e. surrogate key), we have to use business/natural key to implement equals() method. But if we set id field to some unique value (uuid or "app-uid" unique within application) in no-arg constructor, it helps us to implement the equals() method.
public boolean equals(Object obj) {
if(obj instanceof Product) {
Product that = (Product) obj;
return this.id ==that.id;
}
return false;
}
If we or someone else call (intentionally or by mistake) the #PrePersist annotated method more than one times, the "unique id will be changed!!!" So setting id in no-arg constructor is preferable. OR to address this issue put a not null check...
#PrePersist
public void generateId() {
if(id != null)
id = IdGeneratorHolder.getIdGenerator(getClass()).generate();
}
}
UPDATE
If we put the id generation in a
no-arg constructor, wouldn't that
cause a problem when loading entities
from the database? because hibernate
will call the no-arg constructor
causing existing ids to be
re-generated
Yeah you are right, I missed that part. :( Actually, I wanted to tell you that:- in my application every Entity object is associated with an Organization Entity; so I've created an abstract super class with two constructors, and every Entity (except Organization) extends this class.
protected PersistentEntityImpl() {
}
protected PersistentEntityImpl(Organization organization) {
String entityId = UUIDGenerator.generate();
String organizationId = organization.getEntityId();
identifier = new EntityIdentifier(entityId, organizationId);
}
The no-arg constructor is for JPA provider, we never invoke no-arg constructor, but the other organization based constructor. As you can see. id is assigned in Organization based constructor. (I really missed this point while writing the answer, sorry for that).
See if you can implement this or similar strategy in your application.
The second option was using the
#PrePersist annotation. I put that in
and the method never got hit and gave
me an exception stating that I needed
to set the id manually. Is there
something else I should be doing?
Ideally, JPA provider should invoke #PrePersist methods (one declared in class and also all the other methods that are declared in super-classes) before persisting the entity object. Can't tell you what is wrong, unless you show some code and console.
You can.
First, implement org.hibernate.id.IdentifierGenerator
Then you'd have to map it in a mapping xml file. I couldn't find a way to do this with annotations:
<!--
<identifier-generator.../> allows customized short-naming
of IdentifierGenerator implementations.
-->
<!ELEMENT identifier-generator EMPTY>
<!ATTLIST identifier-generator name CDATA #REQUIRED>
<!ATTLIST identifier-generator class CDATA #REQUIRED>
Finally, use #GeneratedValue(generator="identifier-name")
Note that this is hibernate-specific (not JPA)
Update: I took a look at the sources of Hibernate, and it seems at one place, after failing to resolve the short name, hibernates attempts to call Class.forName(..). The parameter there is called strategy. So Here's what you try:
try setting the class fully-qualified name as string in the generator attribute
try setting the class fqn as string in the #GenericGenerator strategy attribute (with some arbitrary name)
Let me know which (if any) worked