0

Hello i have this issue on a custom sequence generator that is not managed by spring context.

This issue came to be when we migrated to hibernate 6 as well as spring-boot 3 and spring 6.

The Problem

I cannot seem to get the values from the property file within my customer generator via @Value

I have annotated @Component to my CustomSequenceGenerator, see below

CustomSequenceGenerator.java

@Component
public class CustomSequenceGenerator extends SequenceStyleGenerator {
  @Value("${value.from.property.file}")
  private String valueFromPropFile;

  @Override
  public Serializable generate(...) {...}

}

MyEntity.java

@Entity
@Table(name="myentity")
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MyEntity {

   @Id
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_gen")
   @GenericGenerator(
        name = "seq_gen",
        strategy = "com.demo.CustomSequenceGenerator",
        parameters = {
           @Parameters(name = "increment_size", value = "1")
        }    
   )
   private String id;

   ...
}

Based on the above code snippet, my value valueFromPropFile is always null.

It seems that CustomSequenceGenerator is not managed by spring. Instead, hibernate is the one instantiating it and that is why i can't get the values from @Value.

Confirmed this when i try to display the Object it self.

in CustomSequenceGenerator.java, in on of the configure method. i put a logging and display this. At the same time, i logged somewhere in a @RestController, the instance of the CustomSequenceGenerator via ApplicatonContext getBean method.

Results were, they have different memory reference. therefore i can conluded that they have different instances.

Question

So my question is, how do i make sure that the instance of CustomSequenceGenerator that is being used by hibernate will be the same instance that is in the spring context. Or how do i make sure hibernate don't instantiate new CustomSequenceGenerator and instead use one from spring context

lemoncodes
  • 2,371
  • 11
  • 40
  • 66

2 Answers2

0

is there any particular reason you want to make the sequence generator a bean?

as long as it implements org.hibernate.id.IdentifierGenerator (it does), you should be able to apply your incremental logic for whatever field you want by using the @GenericGenerator annotation

reference - https://thorben-janssen.com/custom-sequence-based-idgenerator/

i finally made time to try to replicate your problem and the only way i was able to get this to work was passing a value in the jvm arguments via -Dsequence-prefix=ex-prefix- and then pulling that property value without using spring. so in your case:

public class CustomSequenceGenerator extends SequenceStyleGenerator {
  private String valueFromPropFile = System.getProperty("sequence-prefix"); // "ex-prefix-"

  @Override
  public Serializable generate(...) {...}

}

it's kinda ugly but hey it works

vesper
  • 52
  • 6
  • the prefix i want to put is in in the properties file. thats why i need it to be in the spring context hence the use of `@Value` – lemoncodes Jun 16 '23 at 05:04
  • ok i understand, on me for not reading. have you tried using `System.getProperty('value.from.property.file')` ? – vesper Jun 16 '23 at 05:32
  • the only ways i see of meeting your use case is either injecting a "prefix" env variable into your runtime environment or fetching the spring property programmatically – vesper Jun 16 '23 at 05:41
  • yes, i've tried getting it via `System.getProperty` still no success. How do you retrieve the spring props programatically? – lemoncodes Jun 16 '23 at 05:47
  • sorry about all the confusion, it was super late when i first saw this. it doesn't look like there's any way to get the spring properties like you said bc hibernate is doing its own this with the `GenericGenerator` annotation. but plz let me know if my edited answer helps in any way – vesper Jun 16 '23 at 14:18
  • I've managed to find a thread where they get the current application context via a middle man. see my answer – lemoncodes Jun 17 '23 at 12:21
0

I've managed to have a reference to the spring application context based on this question

The idea is, make a spring bean which will inject a the ApplicationContext bean and have it set into a ApplicationContext utility class.

From there, you can use your application context utility class to access the application context instance and get the property field value via applicationContext.getEnvironment().getProperty("prop.file.prefix")

See this code reference on how to setup the application context configuration

Hope this helps everyone get an idea on how to achieve this kind of workaround.

If you have any other idea to achieve the same, please do put your answers. I know there are other ways to achieve the same.

lemoncodes
  • 2,371
  • 11
  • 40
  • 66