I am developing a spring-shell database migration tool.
At the moment i try to use liquibase with the groovy-dsl extension.
My build.gradle includes the extension jar, also i declared liquibase in the spring-shell-plugin.xml
spring-shell-plugin.xml
<bean id="liquibase" class="liquibase.integration.spring.SpringLiquibase" depends-on="postgresService">
<property name="dataSource" ref="psqlDataSource"/>
<property name="changeLog" value="com.example.db.DbChangelog_master"/>
<property name="defaultSchema" value="${postgres.schema}"/>
</bean>
But everytime i start the application liquibase throws the following error
Caused by: liquibase.exception.UnknownChangelogFormatException: Cannot find parser that supports com.example.db.DbChangelog_master
at liquibase.parser.ChangeLogParserFactory.getParser(ChangeLogParserFactory.java:70)
at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:226)
at liquibase.Liquibase.update(Liquibase.java:202)
at liquibase.Liquibase.update(Liquibase.java:192)
at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:434)
at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:391)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 13 more
The documentation is a bit rare, also the jar is included in the classpath.
Does the groovy scripts need to be in src/main/resources? Currently they are in a seperate package in src/main/groovy
I think that your property
<property name="changeLog" value="com.example.db.DbChangelog_master"/>
is incorrect. This should be the path to your changelog file. If that file is a groovy file, it might be
<property name="changeLog" value="DbChangelog_master.groovy"/>
if that file is available on the classpath.
Related
I'm migrating a pretty legacy application to Spring Boot. It is configured with xml and I've got the following snippet there:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="localOverride" value="true"/>
<property name="locations">
<list>
<value>classpath:conf/${ENV}/some.properties</value>
</list>
</property>
</bean>
I'm starting the app with the following command line:
mvn spring-boot:run -Dserver.port=22222 -DENV=int
But it fails on startup with the following message:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'ENV' in value "classpath:conf/${ENV}/some.properties"
It worked before and now I've got spring-boot-starter-web.
Any suggestions? Thank you in advance!
UPDATE: It doesn't work in #PropertySource, not in xml, sorry for misunderstanding
When running the application using maven spring boot plugin(like you are doing) you need to specify like this
mvn spring-boot:run -Drun.arguments="--server.port=22222, --ENV=int"
If you want to run your application using java -jar command. This is the way
java -jar -Dserver.port=22222 -DENV=int XYZ.jar
You should use #systemEnvironment['propertyName'] or
#{systemProperties['propertyName']}
<value>classpath:conf/#{systemEnvironment['ENV']/some.properties</value>
Because
${propertyName}
You can only access properties defined in .properties file
Hello I'm using the following
hibernate-core-4.1.2.Final.jar
mysql-connector-5.1.6.jar
Both can be found in my project lib directory.
I have the following hibernate.cg.xml configuration.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Defines the SQL dialect used in Hiberante's application -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!--Local Database Connection-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/domain</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">test</property>
<property name="hbm2ddl.auto">validate</property>
<property name="show_sql">false</property>
<property name="format_sql">false</property>
<property name="use_sql_comments">false</property>
<property name="hibernate.search.default.directory_provider">ram</property>
</session-factory>
</hibernate-configuration>
and I'm getting the following exception.
Caused by: java.sql.SQLException: No suitable driver found for
jdbc:mysql://localhost:3306/domain at
java.sql.DriverManager.getConnection(DriverManager.java:604) at
java.sql.DriverManager.getConnection(DriverManager.java:190) at
org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl.getConnection(DriverManagerConnectionProviderImpl.java:192)
at
org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:278)
at
org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:297)
... 145 more
I do not want to use JNDI do to the fact management wants to keep the app as portable as possible, so what am I missing to get this to work with jdbc? Am I required to do any kind of configurations to tomcat?
Tomcat Lib
Try putting mysql-connector-5.1.6.jar directly into the lib folder of tomcat and restarting it.
Have you tried calling the driver class?:
Class.forName("com.mysql.jdbc.Driver");
How to call it:
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException ex) {
// error out
}
Connection con = DriverManager.getConnection(/*your connection query*/);
I may have the class wrong, but if com.mysql.jdbc.Driver doesn't work, you can also try com.mysql.JDBC or com.mysql.jdbc (basing off how SQLite calls it)
Did you edit the config to obscure the connection string?
Your hibernate config has a different database name than the error:
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/domain</property>
Caused by: java.sql.SQLException: No suitable driver found for
jdbc:mysql://localhost:3306/etss
In terms of portability, I package the database driver with my war, so it is self contained. This makes for deployment across multiple environments much easier and if another developer wants to build and run locally, they just have to drop the war into Tomcat and go. Place the database driver in your WEB-INF/lib folder.
Also, in terms portability, I recommend JNDI... that way you do not have to edit your hibernate config file when you deploy it to another server and it can stay packaged in your war. You just add the JNDI reference in the Tomcat config.
The exception occurs because the mysql database driver is not on your classpath. Add it to your classpath to repair the issue. Since you are using tomcat you can simply add it to the tomcat/lib directory.
I would suggest putting your drivers in/at where you have place JDK's Extension directory. Please see:http://www3.ntu.edu.sg/home/ehchua/programming/howto/ErrorMessages.html#zz-4.1
Once that is done I would encourage you to from your prompt type:
echo %CLASSPATH%
My spring context file has this:
<context:property-placeholder location="classpath:web.properties" />
and I reference the key/values like:
<property name="username" value="${dataSource.username}"/>
My file layout is like:
>/www/site/app.war
>/www/site/configs/web.properties
And I run my app using:
>java -cp "/www/site/configs/*.*" -jar app.war
But then I get this exception:
java.io.FileNotFoundException: class path resource [web.properties] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:157)
at org.springframework.core.io.support.PropertiesLoaderSupport.loadProperties(PropertiesLoaderSupport.java:181)
at org.springframework.core.io.support.PropertiesLoaderSupport.mergeProperties(PropertiesLoaderSupport.java:161)
at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:78)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:661)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:631)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:588)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:645)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:508)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:449)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:133)
Even though I added the files to my classpath, it still can't find it why?
Update
So my config files are here:
/www/site/configs/web.properties
/www/site/configs/log4j.properties
I tried this:
>/www/site/java -cp ".:app.war:/www/site/configs/*.*" com.abc.server.MyServer
and:
>/www/site/java -cp ".:app.war:/www/site/configs/web.properties:/www/site/configs/log4j.properties" com.abc.server.MyServer
and even:
/www/site/java -cp ".:app.war" com.abc.server.MyServer
I get the same error:
2013-04-25 01:19:28.210:INFO:oejs.Server:jetty-7.x.y-SNAPSHOT
2013-04-25 01:19:28.294:INFO:oejw.WebInfConfiguration:Extract jar:file:/www/site/app.war!/ to /www/site/work/app
2013-04-25 01:19:32.814:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/www/site/app/},file:/www/site/app.war
log4j:WARN No appenders could be found for logger (org.springframework.web.context.support.StandardServletEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
2013-04-25 01:19:33.585:INFO:/:Initializing Spring FrameworkServlet 'app'
2013-04-25 01:19:35.750:WARN:/:unavailable
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in ServletContext resource [/WEB-INF/web-context.xml]: Could not resolve placeholder 'dataSource.url' in string value [${dataSource.url}]
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209)
My web.properties has:
dataSource.url=jdbc:mysql://localhost/appdb
dataSource.username=root
dataSource.password=123
Again my web-context.xml file has:
..
<context:property-placeholder location="classpath*:/web.properties" />
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${dataSource.url}"/>
<property name="username" value="${dataSource.username}"/>
<property name="password" value="${dataSource.password}"/>
..
I also tried the following variations:
<context:property-placeholder location="classpath:web.properties" />
<context:property-placeholder location="classpath*:web.properties" />
<context:property-placeholder location="classpath*:/web.properties" />
I have also faced similar issues. I cannot say why but I have found -cp arguments not to behave when lugged along with -jar.
You can use,
EDIT
As per the dicussion and going through: http://docs.oracle.com/javase/6/docs/technotes/tools/windows/classpath.html
The correct syntax should be:
In windows:
java -cp "app.war;/www/site/configs/" <Main Class file name>
In Linux:
java -cp "app.war:/www/site/configs/" <Main Class file name>
Items accessible via the CLASSPATH aren't necessarily files at all. They might be still in the JAR or WAR file. They should be accessed as resources, via Class.getResource() and friends.
Entries in the CLASSPATH aren't files either. A CLASSPATH is one or more directories or JAR files inside which the resources are to be found, according to the package structure.
This is a "simple" problem and I am seeking both a how-to and/or a you're-dumb-don't-do-that. I am open to both.
I am building a war file and want the structure to be:
WEB-INF/
properties/
<my properties files>
classes/
...
spring/
<my spring files>
Is that dumb? I know that I can access the properties files though the property-placeholder but I'd rather not nest the properties in the classes section - it doesn't make sense to me.
So the Spring file looks like this:
<context:property-placeholder location="classpath:properties/*.properties" />
if I want to access them in the classes area. I thought that
<context:property-placeholder location="properties/*.properties" />
would let me just put the directory under WEB-INF directly...am I wrong (ps I think I am :) ).
Any advice?
This should work
<context:property-placeholder location="WEB-INF/properties/*.properties" />
WEB-INF is not the root of the of the web-app, so you need to add WEB-INF to the path.
spring-context-3.1.xsd
<xsd:attribute name="location" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
The location of the properties file to resolve placeholders against, as a Spring
resource location: a URL, a "classpath:" pseudo URL, or a relative file path.
Multiple locations may be specified, separated by commas. If neither location nor properties-ref is
specified, placeholders will be resolved against system properties.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
You can't do it the way you want since the classpath for the Classloader will be the /classes directory and any jars in the /lib directory. This is the standard configuration for a war file.
Wars and ears have specific configurations which you have to follow for the files to be valid. If you think about it, it would make it difficult to have different vendors provide web containers that could deploy the same war file if there was no standard format. There is a pretty informative page here.
To achieve something similar to what you want, you can simply have directories of /classes/properties and /classes/spring and look them up appropriately from your classpath ("classpath:properties/myfile.properties).
I am not sure what you want to achieve. Here the method I use to inject the properties from a basic properties file to a bean:
In the spring files (XML bean definitions), I add the reference to my property file (myfile.properties):
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:myfile.properties" />
</bean>
and then I add my references to the properties (db.url is the URL address for my database connection, I kept only the bean properties referenced in my property file).
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!-- results in a setDriverClassName(String) call -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"><value>${db.url}</value></property>
<property name="username"><value>${db.login}</value></property>
<property name="password"><value>${db.password}</value></property>
</bean>
By default, if the property is not defined in the property file, Spring uses the System Properties (this behaviour can be changed).
im developing a standalone application and it works fine when starting it from my ide(intellij idea), but after creating an uberjar and start the application from it javax.persistence.spi.PersistenceProvider is thrown saying "No Persistence provider for EntityManager named testPU"
here is my persistence.xml which is placed under meta-inf directory:
<persistence-unit name="testPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>test.model.Configuration</class>
<properties>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.password" value="root"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/test"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>
<property name="hibernate.c3p0.timeout" value="300"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
and here is how im creating the entity manager factory:
emf = Persistence.createEntityManagerFactory("testPU");
im using maven and tried the assembly plug-in with the default configuration fot it, i dont have much experience with assembling jars and i dont know if im missing something, so if u have any ideas ill be glad to hear them
You are probably having problems with your libraries.. Try doing below.
Build your application JAR File
Get all libraries that you have used for the application and put them in a folder lib.
Place your JAR file and lib folder in a new folder say MyApp.
Open your file by using 7-ZIP or WinRAR. Look for Manifest.MF in the META-INF folder.
Your manifest file should look something like..
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.0
Created-By: 1.6.0_03-b05 (Sun Microsystems Inc.)
Main-Class:
Class-Path: lib/.jar lib/.jar lib/.jar ...
I remember having that issue, and I think the problem was that you can't reference a jar in a jar. For your external libraries, they need to be expanded inside your jar or live elsewhere on the system CLASSPATH. So since you don't specify what all you're putting in your jar, I'm betting on this one.
You can NOT use the -cp command line parameter if you run your jar using the -jar parameter. One or the other.
When using the Maven Assembly Plugin with the predefined jar-with-dependencies descriptor, you get a jar archive which contains the binary output of your project, along its the unpacked dependencies. So one possible problem I can think of would be multiple JARs with persistence.xml, in which case I'm not sure which one you'll get in the final assembly.
Since you get an error message complaining about "No Persistence provider for EntityManager named testPU", I would open the megajar and:
check that the persistence.xml is present (it should)
check that it contains the expected persistence unit testPU
if it doesn't, find the origin of the conflicting file and rewrite the assembly descriptor to exclude it