#EnableJpaRepositories annotation disables data.sql initialization script - database

My Spring Boot (v2.3.4) based application uses my custom library containing core entities and business logic. To use entities and repositories from this library I had to use #EnableJpaRepositories and #EntityScan annotations with proper packages provided.
I also wanted to initialize database with some required data (let's say the configuration) during application startup. I found that Spring Boot allows to use data.sql or data-${platform}.sql files to achieve that.
Long story short when using #EnableJpaRepositories annotation the data.sql script is not executed.
I did some digging in the code and found that when #EnableJpaRepositories annotation is not used then entityManagerFactory bean is of org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean type. This bean uses org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher bean post processor, which fires org.springframework.boot.autoconfigure.jdbc.DataSourceSchemaCreatedEvent event indicating the schema has been created. Class, which listens for this event is org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker. This listener invokes initSchema() method from org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer class. This method is responsible for whole initialization using data.sql script.
It looks like setting #EnableJpaRepositories annotation creates instance of different class for entityManagerFactory bean, which does not support this simple initialization.
My basic question is then how to make it all work with #EnableJpaRepositories annotation. I can always use Hibernate's import.sql file (which works fine) but I'm also trying to understand what exactly is going on under the hood I how can I control it.
UPDATE 1 28.09.2021
I did further investigation and #EnableJpaRepositories annotation does not change the instance type of entityManagerFactory but it causes silent exception (?) when creating org.springframework.scheduling.annotation.ProxyAsyncConfiguration bean (during creation of org.springframework.context.annotation.internalAsyncAnnotationProcessor bean). It looks like everything is related to #EnableAsync annotation, which I'm also using but didn't know it might be related. But it is - removing it makes the initialization work even with #EnableJpaRepositories.
UPDATE 2 28.09.2021
I've found full explanation for my issue. There are 4 conditions, which must be met to reproduce the issue:
#EnableJpaRepositories annotation in application configuration
#EnableAsync annotation in application configuration
Configuration implements AsyncConfigurer interface
Autowired any JpaRepository repository or any other bean which injects repository
Enabling asynchronous execution and implementing AsyncConfigurer makes the whole configuration to be instantiated before regular beans. Because Spring has to inject repository, it needs to instantiate entityManagerFactory bean too. Spring prints thenINFO level logs like below:
Bean 'entityManagerFactoryBuilder' of type [org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
One of not eligible BeanPostProcessors is DataSourceInitializedPublisher responsible for firing DataSourceSchemaCreatedEvent event. Without that event, data-${platform}.sql script won't be processed at all.
I'm not sure what is the role of #EnableJpaRepositories in that process but without it the problem does not occur.
Example
Minimal code to reproduce the issue (data.sql located in src/main/resources):
#Entity
public FileStore {
...
}
public interface FileStoreRepository extends extends JpaRepository<FileStore, Long> {
}
#Configuration
#EnableAsync
#EnableJpaRepositories
public class Configuration implements AsyncConfigurer {
#Autowired
private FileStoreRepository fileStoreRepository;
...
}
Solutions
There are two solutions I'm aware of:
Move AsyncConfigurer along with its overrided methods and #EnableAsync annotation to separate configuration class
Use #Lazy annotation on autowired bean like below:
#Lazy
#Autowired
private FileStoreRepository fileStoreRepository;
Similar problem was pointed by #Allen D. Ball and can be checked there.

This behavior had changed.
Take a look at the
how-to guide.
Add:
spring.jpa.defer-datasource-initialization: true

Related

Camel Salesforce - Multiple Components Configurations

I am trying to configure multiple Camel Salesforce components in the same camel context. As I need to connect two different salesforce instances.
I know in order to configure another instance, we can simply create a new bean with a different name and it can then be used in endpoint configurations.
I got one configured via standard properties configurations and the second one is configured using a bean with different properties.
But on startup my second bean configurations get overwritten by main components configurations in SalesforceComponentConfigurer class.
Is there any way to stop configurer to ignore the second component?
#Bean("salesforce-target")
public SalesforceComponent targetSalesforceComponent(#Autowired CamelContext camelContext) {
SalesforceComponent targetComponent = new SalesforceComponent(camelContext);
targetComponent.setClientId(clientId);
targetComponent.setClientSecret(clientSecret);
targetComponent.setUserName(userName);
targetComponent.setPassword(password);
targetComponent.setLoginUrl(loginUrl);
targetComponent.setLazyLogin(true);
targetComponent.setAuthenticationType(AuthenticationType.USERNAME_PASSWORD);
return targetComponent;
}

Using timers in jboss modules

I am required to create a timer/schedule service in jboss (JEE6). The issue is, it gets deployed as jboss module. I know that following code works if deployed as EJB
#Schedule(hour="*/1", persistent=false)
but it doesnt work if deployed otherwise. Are there any recommendations or standard ways to create and use timers in jboss modules? I want to avoid core-java way of creating TimerTask.
jboss modules are created for sharing code across applications in an efficient way. For more refer here. Now, because modules are not deployed in EJB container; its not possible to use EJB scheduler here. The possible solution or way around for this in our case was to create an EJB which has dependency on these jboss modules whose methods will be invoked by schedulers.
for example,
#Singleton
#Startup
public class NotificationRecorderBean {
#Inject
private MyJbossModule myJbossModule;
#Schedule(hour="*/1", persistent=false)
public void execute() {
LOGGER.debug("Recording notification count");
myJbossModule.process();
}
}

Unable to generate cloud endpoint class

Dear fellow programmers,
I am very new to programming and i am following the tutorial on using app engine backend tutorial. However i face some problem along the way.
I have Setup App Engine Backend Application Project, created a CheckIn entity class.
After which, i follow the instruction to create a new class with the name CheckInEndPoint.java
I copy the code from the snippet over to the Class.
When i try to Generate Cloud Endpoint Class, i faced an error message.
Error Generating API
This is not a JDO/JPA entity class.
Kindly seek your advice on how to troubleshoot it.
https://cloud.google.com/developers/articles/how-to-build-mobile-app-with-app-engine-backend-tutorial#ecdp
The instructions as provided by Google are confusing. What the instructions intended to say is after creating CheckIn.java, right-click on the CheckIn.java file and select Google->Generate Cloud Endpoint Class. This will then automatically create the CheckInEndpoint.java file.
Read through the entire "Entity Design Class Pattern" paragraph as given in the link you provided. You'll recognise that their instructions are ambiguous and is actually meant to be carried out from point 6.
Try adding this annotation to your CheckIn class:
import javax.jdo.annotations.PersistenceCapable;
#PersistenceCapable
public class CheckIn ...
This way it will find it as a JDO entity class and it will generate your CheckInEndPoint class.
I had the same error, I have first renamed the class CheckInEndPoint I've created manually to avoid any kind of conflicts. After that I have right clicked on
CheckIn class -> Google ->Generate Cloud Endpoint Class.
If you get some dependencies errors, please try check whether all the classes like ApiKeysAndIds.java, UserAccount.java are in the package.

java.lang.IllegalArgumentException: can't accept class com.veersoft.gwt.shared.trailbalance.TrailBalanceClassResult as a memcache entity

Inorder to make my application faster, I'm using the MemcacheService. Now, while I'm trying to put an object into the MemcacheService, I'm getting the following error:
java.lang.IllegalArgumentException: can't accept class com.veersoft.gwt.shared.trailbalance.TrailBalanceClassResult as a memcache entity.
Details about the entity:
It's a normal Bean which implements IsSerializable interface.
It is not a dataStore entity. I'm using this just to render at the browser side(i.e., the deferred task will calculate the results and will send these results to the browser).
To put any object in memcache, it needs to implement the Serializable interface. IsSerializable is an anachronism from an old version of GWT and does not affect java serialization in any way.

Guice and JSF 2

I'm trying to use Guice to inject properties of a JSF managed bean. This is all running on Google App Engine (which may or may not be important)
I've followed the instructions here:
http://code.google.com/docreader/#p=google-guice&s=google-guice&t=GoogleAppEngine
One problem is in the first step. I can't subclass the Servlet module and setup my servlet mappings there because Faces is handled by the javax.faces.webapp.FacesServlet which subclasses Servlet, not HttpServlet. So, I tried leaving my servlet configuration in the web.xml file and simply instantiating a new ServletModel() along with my business module when creating the injector in the context listener described in the second step.
Having done all that, along with the web.xml configuration, my managed bean isn't getting any properties injected. The method is as follows
#ManagedBean
#ViewScoped
public class ViewTables implements Serializable
{
private DataService<Table> service;
#Inject
public void setService( DataService<Table> service )
{
this.service = service;
}
public List<Table> getTables()
{
return service.getAll();
}
}
So, I'm wondering if there is a trick to get Guice injecting into a JSF managed bean? I obviously can't use the constructor injection because JSF needs a no-arg constructor to create the bean.
Check the following JSF-Guice integration framework/advice:
http://code.google.com/p/jsf-sugar/
http://notdennisbyrne.blogspot.com/2007/09/integrating-guice-and-jsf.html
http://cagataycivici.wordpress.com/2007/03/26/integrating_guice_and_jsf/
http://snippets.dzone.com/posts/show/7171
You can also create an HTTP servlet that then simple delegates the request on to a FacesServlet (like a wrapper). This should give you the same effect using Guice Servlet.
How about this approach, works well for us:
http://uudashr.blogspot.com/2008/12/guicing-jsf-with-guice.html
being the developer of jsf sugar I really would like to know the problem you had using it. We are already using it in production here so there shouldn't be any "show stoppers", maybe something is just not well documented? Just drop me a mail: murbanek(at)gmx_net (replace the _ with a .) .
check out http://code.google.com/p/guice2jsf/, and website starchu.blogspot.com, it has excellent library that provides Guice and JSF 2.0 integration
As information in this post are getting out of date but the question is still relevant, I'd like to share my findings about this topic. I wrote a little tutorial including a runnable sample project on how to setup a fully guice powered web stack. You can find it here: https://github.com/skuzzle/guice-jsf

Resources