Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mariaDB4j-springboot module for auto-configuration with spring boot #153

Closed
wants to merge 9 commits into from

Conversation

@kbyyd24
Copy link
Contributor

kbyyd24 commented Aug 17, 2018

Add a module named mariaDB4j-springboot, it will auto-configure MariaDBSpringService as a bean named mariaDB4j, and initialize bean dataSource after mariaDB4j initialized by annotation @DependsOn.
So now, we can use mariaDB4j with spring boot with dependency of mariaDB4j-springboot. For example, we can configure gradle like this:

dependencies {
    compile 'org.springframework.boot:spring-boot-starter'
    testCompile 'ch.vorburger.mariaDB4j:mariaDB4j-springboot:2.3.1-SNAPSHOT'
}
@duttonw

This comment has been minimized.

Copy link
Contributor

duttonw commented Aug 19, 2018

can you update the readme in the root on how to use this as well as create an example integration project to has sample config setup with spring boot. (how you will use this in a simple spring-boot app)
see https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-flyway but for MariaDB4j instead.

@kbyyd24

This comment has been minimized.

Copy link
Contributor Author

kbyyd24 commented Aug 19, 2018

@duttonw I will update the readme in the root. But it's necessary to create another example integration project to has sample config setup with spring boot? I think mariaDB4j-app is a sample of it, maybe what I need to do is update it. Is it OK to change mariaDB4j-app?

@vorburger

This comment has been minimized.

Copy link
Owner

vorburger commented Aug 19, 2018

I think mariaDB4j-app is a sample of it, maybe what I need to do is update it. Is it OK to change mariaDB4j-app?

That makes sense to me, yes - go for it.

@kbyyd24

This comment has been minimized.

Copy link
Contributor Author

kbyyd24 commented Aug 20, 2018

I updated mariaDB4j-app module as an example of usage of mariaDB4j-springboot. And I tried to update readme how(Spring) section, but I'm not sure if the readme make sense, maybe you could review it.

@duttonw

This comment has been minimized.

Copy link
Contributor

duttonw commented Aug 20, 2018

Hi @kbyyd24 ,

I've reworded it a bit for you, you could use it as it, change it, await @vorburger input or all of the above ;).

MariaDB4j can be used in any Java Application on its own. It is not dependent on dependency injection or the Spring Framework (the dependency to the spring-core*.jar is for a utility, and is unrelated to DI).

If you want to use MariaDB4j with Spring-boot the opinionated presets for spring applications, then you can easily use this the ready-made MariaDB4jSpringService to reduce your coding/configuration to get you going, we have an example application ([MariaDB4jApplication](https://github.com/vorburger/MariaDB4j/blob/master/mariaDB4j-app/src/main/resources/application.yml)) which illustrates how to wire it up or as an alternative approach via the [MariaDB4jSpringServiceTestSpringConfiguration](https://github.com/vorburger/MariaDB4j/blob/master/mariaDB4j/src/test/java/ch/vorburger/mariadb4j/tests/springframework/MariaDB4jSpringServiceTestSpringConfiguration.java).

The DataSource initialization have to wait until MariaDB is ready to receive connections, so we provide mariaDB4j-springboot to implement it. You can use it by :

dependencies {
    testCompile("ch.vorburger.mariaDB4j:mariaDB4j-springboot:2.3.1-SNAPSHOT")
}
In the module, bean name of MariaDB4jSpringService is mariaDB4j, and dataSource depends on it by name. So if you want to customize your mariaDB4j, please make sure the name is correctly.

In [issue #64](https://github.com/vorburger/MariaDB4j/issues/64) there is also a discussion about it and pointing to a TestDbConfig.java gist.

Don't know if you found this but this is quite helpful for spring work and javascript integrations. https://www.jhipster.tech/ and from your blog, i really like how your post on "Customize Validation in Java"

@vorburger

This comment has been minimized.

Copy link
Owner

vorburger commented Aug 20, 2018

@kbyyd24 if you work @duttonw feedback into this and resolve the minor new merge conflict, I'd review this.

kbyyd24 added 2 commits Aug 21, 2018
@kbyyd24

This comment has been minimized.

Copy link
Contributor Author

kbyyd24 commented Aug 21, 2018

@vorburger I updated readme, almost like @duttonw feedback, the only thing different is the link to the example application, I changed it to mariaDB4j-app. I Also resolved the conflict. So I think it's ready to be review.

@kbyyd24

This comment has been minimized.

Copy link
Contributor Author

kbyyd24 commented Aug 21, 2018

@duttonw Thanks for your feedback about the readme and my blog. I have updated the readme as you feedback. For the JHipster, I had never heard about it, I will try it for a demo. Thanks for your recommend.
By the way, how can you read my blog? It Chinese, do you know that?

@duttonw

This comment has been minimized.

Copy link
Contributor

duttonw commented Aug 21, 2018

Hi @kbyyd24 ,

Google chrome allows language translation with a click of a button or like this

@kbyyd24

This comment has been minimized.

Copy link
Contributor Author

kbyyd24 commented Aug 21, 2018

@duttonw Oh, I forgot it 😂

@duttonw

This comment has been minimized.

Copy link
Contributor

duttonw commented Aug 22, 2018

Hi @kbyyd24 , could you please rebase this as master has had some squashes from other pull request merging.

@kbyyd24

This comment has been minimized.

Copy link
Contributor Author

kbyyd24 commented Aug 22, 2018

Hi @duttonw , I don't know how to do that. I clicked the "Update branch" button, then triggered travis automatically. After pipeline passed, this page looked like the picture. Is the rebase done?

image

@duttonw

This comment has been minimized.

Copy link
Contributor

duttonw commented Aug 22, 2018

Cool, now it just needs @vorburger to do a final review and merge :D 👍

@kbyyd24

This comment has been minimized.

Copy link
Contributor Author

kbyyd24 commented Aug 22, 2018

That's cool, Thank you for your help 👍

<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>

This comment has been minimized.

Copy link
@vorburger

vorburger Aug 24, 2018

Owner

why is this needed here?

This comment has been minimized.

Copy link
@kbyyd24

kbyyd24 Aug 25, 2018

Author Contributor

In mariaDb4j-springboot module, it create a bean of DataSource, so we need some implement of Spring Data in spring application. I added spring-boot-starter-data-jpa, then I run the test of the application, I got an exception:

java.lang.IllegalStateException: Failed to load ApplicationContext

	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1699)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1089)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:859)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:398)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:330)
	at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:139)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117)
	... 24 more
Caused by: java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
	at org.hibernate.boot.spi.XmlMappingBinderAccess.<init>(XmlMappingBinderAccess.java:43)
	at org.hibernate.boot.MetadataSources.<init>(MetadataSources.java:87)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:209)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:164)
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:51)
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390)
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377)
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1758)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1695)
	... 39 more
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
	... 50 more

Honestly, I don't why it happened, and I had never got this exception. But the exception disappeared when I add this dependency.

I've changed to use spring-boot-starter-jdbc, so we don't need this any more.

<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>2.2.6</version>

This comment has been minimized.

Copy link
@vorburger

vorburger Aug 24, 2018

Owner

I doubt this is needed, have you tried without it?

Note it currently works without this....

The parent/root POM already has this dependency.

Why fix a more recent version? If it were absolutely needed (I doubt it, easier to inherit it from the Spring BOM instead of having to keep bumping it here @duttonw), why only here, not in the parent?

This comment has been minimized.

Copy link
@kbyyd24

kbyyd24 Aug 25, 2018

Author Contributor

I can't find the dependency in the parent/root POM. I can only find it in mariaDB4j module and it's scope is test. So need I add the dependency in the parent/root POM?

This comment has been minimized.

Copy link
@vorburger
@@ -63,6 +62,7 @@ public static void main(String[] args) throws Exception {

@Override
public int getExitCode() {
MariaDB4jSpringService dbService = applicationContext.getBean(MariaDB4jSpringService.class);

This comment has been minimized.

Copy link
@vorburger

vorburger Aug 24, 2018

Owner

it's been many years since I last used the Spring Framework myself (doing other things nowadays), but wasn't the idea that explicitly looking up beans is bad? I thought it was much better DI practice to just inject what you needed. So why change the @Autowired MariaDB4jSpringService to an applicationContext.getBean(MariaDB4jSpringService.class) ?

This comment has been minimized.

Copy link
@kbyyd24

kbyyd24 Aug 25, 2018

Author Contributor

You are right, I fixed this.

password:

mariaDB4j:
port: 3307

This comment has been minimized.

Copy link
@vorburger

vorburger Aug 24, 2018

Owner

hard-coding to port 3307 means this fails if one runs this on a system where there already is a mysqld running (e.g. from a RPM / DEB launched by systemd). The original mariaDB4j.port=0 thing let it automatically choose a free port - that was cool. Is it possible to retain a similar solution? Perhaps it's even enough to simply try out port: 0 here?

This comment has been minimized.

Copy link
@kbyyd24

kbyyd24 Aug 25, 2018

Author Contributor

That's a good point. But Spring cannot get the dynamic port automatically, so I have to do something when create bean dataSource.

This comment has been minimized.

Copy link
@duttonw

duttonw Aug 26, 2018

Contributor

Hi @kbyyd24 , have you looked at how in-memory db's get their dynamic port?

This comment has been minimized.

Copy link
@kbyyd24

kbyyd24 Aug 26, 2018

Author Contributor

@duttonw No, I don't know how spring get that. I will research about that.

This comment has been minimized.

Copy link
@kbyyd24

kbyyd24 Aug 26, 2018

Author Contributor

Hi @duttonw , I found that h2, hsql and derby are auto configured in Spring Boot, and they are in-memory DB. So they are running in the same process with Spring Boot. Then we don't need any port to connect to them.
In this case, mariaDB4j is not in-memory DB, so we need to determine a port. I'm going to change the logic of creation dataSource bean. Maybe we don't need use property of spring.data here, we can use mariaDB4j.port, mariaDB4j.db-host, mariaDB4j.username and etc.

* #%L
* MariaDB4j
* %%
* Copyright (C) 2012 - 2014 Michael Vorburger

This comment has been minimized.

Copy link
@vorburger

vorburger Aug 24, 2018

Owner

nit picking, sorry but could you put "2012 - 2018" here?

This comment has been minimized.

Copy link
@kbyyd24

kbyyd24 Aug 25, 2018

Author Contributor

Thank you for your mention, I had never notice this 😂.
Now it fixed.

* #%L
* MariaDB4j
* %%
* Copyright (C) 2012 - 2014 Michael Vorburger

This comment has been minimized.

Copy link
@vorburger

This comment has been minimized.

Copy link
@kbyyd24

kbyyd24 Aug 25, 2018

Author Contributor

Fixed.

kbyyd24 and others added 4 commits Aug 25, 2018
Copy link
Owner

vorburger left a comment

LGTM. I'll follow-up re. the mariadb-java-client in a separate new PR from me which you can review, and have opened #163.

@vorburger

This comment has been minimized.

Copy link
Owner

vorburger commented Aug 27, 2018

merged as d3be03e

@vorburger vorburger closed this Aug 27, 2018
kbyyd24 added a commit to kbyyd24/MariaDB4j that referenced this pull request Feb 17, 2019
kbyyd24 added a commit to kbyyd24/MariaDB4j that referenced this pull request Feb 17, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.