PhysicalNamingStrategy bean only instantiates via config file - java

I have a custom naming strategy in a Spring app with Hibernate:
public class MyCustomPhysicalNamingStrategy implements PhysicalNamingStrategy {
#Override
public Identifier toPhysicalTableName(Identifier identifier, JdbcEnvironment jdbcEnvironment) {
return Identifier.toIdentifier("my_custom_table_name");
}
// ...
}
The Spring documentation says I can tell Hibernate to use it either by setting spring.jpa.hibernate.naming.physical-strategy (which works fine), or like this:
Alternatively, if ImplicitNamingStrategy or PhysicalNamingStrategy beans are available in the application context, Hibernate will be automatically configured to use them
I need to use this second method, as I need to pass some info from Spring's context to my naming strategy. However, I can't get it to work.
I'm creating the bean in the following configuration class:
#Configuration
public class PersistenceConfiguration {
#Bean
public PhysicalNamingStrategy physicalNamingStrategy() {
return new MyCustomPhysicalNamingStrategy();
}
}
What am I missing here?
Thanks in advance.
EDIT: I'm on Spring Boot/Spring JPA 1.5.9.RELEASE, which gives me Hibernate core v.5.0.12.Final and Hibernate JPA API 2.1.

It seems that this is only supported with spring boot 2.
See: https://github.com/spring-projects/spring-boot/blob/v2.0.3.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.java#L95
This file is not present in spring boot 1.5: https://github.com/spring-projects/spring-boot/tree/v1.5.14.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa
(HibernateJpaAutoConfiguration.java doesn't have it)

Related

is it possible to have Spring configuration relying only on annotations apart from being spring boot application?

I'm new in Spring applications, and see the big difference between configurations in springBoot and spring. So my questin is: apart from spring-boot, is there a way to setup a proper spring application(with web mvc, security, aop, ...), without any xml config file (ie : config relying only on annotations).
Yes, there is a way to do this in Spring. Spring Boot is after all an enhanced, autoconfigured Spring (with other cool features). That means that everything there is in Spring Boot should be achievable in Spring as well, but you would have do a bit/a lot of Your own extra work.
Moving straight to the point, in order to achieve what you want, you would need to undertake the following steps:
Create a class, which will store all the configuration (basically the properties you would store in the xml file) - let's call it AppConfig.class
Annotate the AppConfig.class with #Configuration - this will inform Spring that this class is the source of configuration;
Annotate the AppConfig.class with #ComponentScan("com.app") - here, You need to provide a package, from which Spring has to start component scanning in order to find Beans to be registered in Spring Container. Important note is, that it will scan the package and it's subpackages, so you would mostly want to provide here the top level package;
If you need some data to be injected into your beans, you would want to use the #PropertySource("classpath:application.properties") - I have provided here the default value, which Spring Boot uses internally in case you want to inject some data into your beans at runtime. For this to work, you need to inject into AppConfig.class an Environment.class
To show it on the example:
#Configuration
#ComponentScan("com.app")
#PropertySource("classpath:application.properties")
public class AppConfig {
// it will help to pull the properties incorporated in the file you have provided in the #PropertySource annotation
private Environment environment;
//inject it
public AppConfig(Environment environment) {
this.environment = environment;
}
// build your beans - the getProperty method accepts the key from application.properties
// file and return a value as a String. You can provide additional arguments to convert
//the value and a default value if the property is not found
#Bean
public Product product() {
return new Product(
environment.getProperty("product.name", "XXX"),
environment.getProperty("product.price", BigDecimal.class, BigDecimal.ZERO),
environment.getProperty("product.quantity", Integer.class, 10)
);
}
}
I hope that it helps

Custom `RelyingPartyRegistrationRepository` implementation

It looks like Spring always uses InMemoryRelyingPartyRegistrationRepository to return a RelyingPartyRegistrationRepository typed bean, refer to https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyRegistrationConfiguration.java.
Question: how can I inject (autowire) my own implementation of RelyingPartyRegistrationRepository? Say I would like to allow the auto wired relying party repository auto reload from database once I have SAML configuration for a certain customer updated. Is this doable?
You can provide your own bean and spring boot auto configuration will back off.
#Configuration
#EnableConfigurationProperties(Saml2RelyingPartyProperties.class)
public class SamlConfig{
#Bean
RelyingPartyRegistrationRepository relyingPartyRegistrationRepository(Saml2RelyingPartyProperties properties) {
-- Provide custom repository implementation
}
}
You may need other changes after you create your own bean based on what you need.

Multiple Constructor injection ambiguity with spring boot

I am trying to learn to migrate one spring XML based application to spring boot application and wondering with one scenario where we have multiple constructors in a class and wish to inject all these using spring annotation.
I do understand and implemented the way using XML based configuration but confused with which annotation/way to inject multiple constructors.
I tried referring to few forums like : Ambiguity Regarding Spring Constructor Injection but no luck with spring boot.
Could anyone please help on this please?
As it was mentioned in comments you can use #Configuration
#Configuration
public class Config {
#Bean
public Employee employee() {
return new Employee(10,"100");
}
}

Run Flyway Java-based callbacks with Spring Boot

Is there a way to run Flyway Java-based callbacks with Spring boot?
I'm converting an existing project that after each migration updates some view definitions, and this is done by Java as it needs some extra logic. I know it could be done in pl/pgsql (we are using Postgres) but it is already done and tested in Java.
Spring boot docs says it is possible, but it is listed that the callback scripts should live in same dir as migrations, maybe this works just for SQL based callbacks.
This code works without Spring Boot:
Flyway flyway = new Flyway();
flyway.setDataSource(this.getDataSource());
flyway.setLocations("/db/migration");
flyway.setCallbacks(new LogMaintenanceFlywayCallback());
flyway.migrate();
I have several migrations in /db/migration and after each one I need to execute my callback. It works in my current project and I need to do the same (or another way to get the same behavior) in Spring Boot.
You can have a configuration like this and it will work:
#Configuration
public class FlywayFactory {
#Bean
public FlywayMigrationInitializer flywayInitializer(Flyway flyway, FlywayCallback flywayCallback) {
flyway.setCallbacks(flywayCallback);
return new FlywayMigrationInitializer(flyway);
}
#Bean
public FlywayCallback flywayCallback() {
return new LogMaintenanceFlywayCallback();
}
}
Since method setCallbacks(Callback... callbacks) of the Flyway has been deprecated and will be removed in Flyway 6.0, you can use new API and FlywayConfigurationCustomizer to set up custom Java-based callbacks. Then the configuration is as below:
#Configuration
public class FlywayFactory {
#Bean
public FlywayConfigurationCustomizer flywayConfigurationCustomizer() {
return configuration -> configuration.callbacks(new LogMaintenanceFlywayCallback());
}
}
There seems to be no possibility to set the callbacks in the Spring Boot autoconfiguration (See FlywayAutoConfiguration.java)
There are 2 things you can do:
Create your own Flyway instance in one of your Configuration classes. Spring Boot will not create his instance in case you do that.
Autowire the Flyway instance in one of your Configuration classes and call the setCallbacks method in a PostConstruct method (But it might be tricky to make sure you call the setter before the migration starts)
You can override the Flyway migration stragtey
#Component
public class CallbackFlywayMigrationStrategy implements FlywayMigrationStrategy {
#Override
public void migrate(Flyway flyway) {
flyway.setCallbacks(new LogMaintenanceFlywayCallback());
flyway.migrate();
}
}
You can define a bean of type org.flywaydb.core.api.callback.Callback as follows:
#Bean
public Callback logMaintenanceFlywayCallback() {
return new LogMaintenanceFlywayCallback();
}

Boot-strapping Spring Data JPA without XML

What is the Java #Configuration equivalent to:
<repositories base-package="com.acme.repositories" />
in Spring Data JPA? I am trying to get rid of XML configuration in favour to #Configuration classes, however reading through JpaRepositoryConfigDefinitionParser sources is fruitless.
The closest what I can get is:
#Bean
public RepositoryFactorySupport repositoryFactory() {
return new JpaRepositoryFactory(entityManagerFactory().createEntityManager())
}
#Bean
public BookDao bookDao() {
return repositoryFactory().getRepository(BookDao.class)
}
However the <repositories/> tag is much more functional: it automatically creates DAO for all interfaces extending CrudRepository found on CLASSPATH. Also it seems like my solution does not apply transactions to DAOs as opposed to default Spring Data JPA behaviour.
Spring Data JPA introduced #EnableJpaRepositories. See the reference documentation for details.
Looks like not possible yet: https://jira.springsource.org/browse/DATAJPA-69

Categories

Resources