Spring Liquibase tries to resolve file path to URL - spring

I configured liquibase like this:
#Bean
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setDataSource(getConfiguredDataSouce());
liquibase.setChangeLog("classpath*:config/liquibase/master.xml");
liquibase.setContexts("development,test,production");
LOG.debug("Configuring Liquibase");
return liquibase;
}
my master.xml file:
<includeAll path="classpath*:/config/liquibase/changelog/" relativeToChangelogFile="false"/>
When I run my application on Tomcat (7.0.50 and 8.0.20) it prints this exception:
Caused by: java.io.FileNotFoundException: class path resource [D:/proiecte/ALE MELE/Rezervari/target/Rezervari/WEB-INF/classes/config/liquibase/changelog/20150329182213.xml] cannot be resolved to URL because it does not exist
at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:178)
at liquibase.integration.spring.SpringLiquibase$SpringResourceOpener.getResourcesAsStream(SpringLiquibase.java:109)
at liquibase.util.StreamUtil.singleInputStream(StreamUtil.java:181)
at liquibase.parser.core.xml.XMLChangeLogSAXParser.parseToNode(XMLChangeLogSAXParser.java:93)
... 73 more
That file exists on that path, but it tries (for I don't know what reason) to resolve it to an URL.
Any ideas? :)
P.S.: Liquibase version is 3.2.2.
Thank you,
Tekin.

For me the issue was in extra slash (local, MacOS):
"classpath:config/liquibase/changelog/" - works well.
"classpath:/config/liquibase/changelog/" - does not work.

This may be the same as CORE-2186 on the Liquibase Jira. I get the same symptoms when trying to use includeAll running from Ant.
The original reporter on that bug has added a proposed fix, though just as a comment to the report. I haven't tried it yet.

Related

Spring Boot Application - Running jar file gives ResourceFinderException error

Created a jar file for a spring boot multimodule application and ran the jar file using java -jar command. While starting the application, it gives ResourceFinderException. When I analyzed it, the issue is happening because in my ResourceConfig file, i have used the package for my api end points. If I use register(service.class), the application starts fine. Any suggestion how can I provide the package instead of using register? The reason I want to use package is because I have lots of services inside multiple packages and the code looks very ugly if i use register for all the services. The ResourceConfig file looks like below.
public class AppResourceConfig extends ResourceConfig {
public AppResourceConfig {}{
super();
property("jersery.config.beanValidation.enableOutputValidationErrorEntity.server");
**packages("com.api");**
register(GsonProvider.class);
register(RequestContextFilter.class);
register(NotFoundExceptionMapper.class);
register(DefaultExceptionMapper.class);
}
}
Here the issue is with highlighted line: packages("com.api")
If I comment out this code application will be up. Otherwise it is giving org.glassfish.jersey.server.internal.scanning.ResourceFinderException: java.io.FileNotFoundException: api-01.03.00.04-snapshot.jar (No such file or direcotry)
Note: api-01.03.00.04-snapshot.jar is the jar file for one of the module in a project

Running 'mvn clean install' on Spring Boot application using env variables in application.properties

Hello I am trying to package my Spring Boot app into a jar.
I want to deploy this app to AWS Beanstalk and so I will be injecting some variables into application.properties using Environment variables.
spring.data.mongodb.uri=${MONGODB_URI}
spring.data.mongodb.auto-index-creation=true
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1
CLOUDINARY_URL=${CLOUDINARY_URL}
jwt-secret=${JWT_SECRET}
server.port=5000
However when I run the maven command (mvn clean install), during the package process the code is executed and it is failing stating that
BeanCreationException: Error creating bean with name 'customBeansConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'CLOUDINARY_URL' in value "${CLOUDINARY_URL}"
I have a class CustomBeansConfig:
#Configuration
public class CustomBeansConfig {
#Value("${CLOUDINARY_URL}")
private String cloudinaryUrl;
#Bean
public Cloudinary cloudinary(){
System.out.println("cloudinaryUrl = " + cloudinaryUrl);
return new Cloudinary(cloudinaryUrl);
}
}
Please help me to create the jar file
If I have understood you correctly, one approach may be to use different application.properties files for different environments. For example application-dev.properties for the Dev environment and application-prod.properties for the Prod environment. Then your CLOUDINARY_URL may be assigned different literal values appropriate to each.
Then when deploying to each environment, bundle your JAR with the -Denv option, as in
mvn -Denv=dev clean install
OR
mvn -Denv=prod clean install
... and upload the resulting JAR file to the corresponding AWS environment.
Running the Spring Boot application with a such config property, got me the following error:
Caused by: java.lang.IllegalArgumentException: Circular placeholder reference 'CLOUDINARY_URL' in property definitions
Changing the name of your Spring property from CLOUDINARY_URL to, for example, cloudinary.service.url will resolve the issue.
In such case, your config file should look like this:
spring.data.mongodb.uri=${MONGODB_URI}
spring.data.mongodb.auto-index-creation=true
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1
cloudinary.service.url=${CLOUDINARY_URL}
jwt-secret=${JWT_SECRET}
server.port=5000
And your configuration file like this:
#Configuration
public class CustomBeansConfig {
#Value("${cloudinary.service.url}")
private String cloudinaryUrl;
#Bean
public Cloudinary cloudinary(){
System.out.println("cloudinaryUrl = " + cloudinaryUrl);
return new Cloudinary(cloudinaryUrl);
}
}
Also, I would advise you to avoid creating Spring configuration properties using the underscore format, since it usually used for the environment variables, maybe be confusing and may cause such interesting issues.

Gradle and Flyway: Unable to obtain inputstream for resource

I have the problem that migrateDb using Flyway in a Gradle project sometimes causes
Unable to obtain inputstream for resource: META-INF/db/mysql/V1__script.sql
This error doesn't occur all the time but only sometimes but if it happens it's quite persistent and also a clean/rebuild of the project doesn't solve it.
The SQL script that is mentioned is contained within a JAR file that is referenced from the project as part of a multi module project.
My researched only brought me to https://github.com/flyway/flyway/issues/702 but this didn't lead me to the right way.
I'm also very confused that flyway is able to find the file during the classpath search but is then not able to get the input stream.
If you should need any further info please ask.
Further debugging: It seems that the error seems to happen as soon as a new file is added to the DB JAR. After rebuild and migrateDb the error occurs. If I remove the script again the error still occurs although the script is not in the generated JAR anymore. So I guess the classpath for searching for scripts and retrieving input stream is different. Does anybody know what differences there might be?
Complete stack trace:
Caused by: org.flywaydb.core.api.FlywayException: Unable to obtain inputstream for resource: META-INF/db/mysql/V1__script.sql
at org.flywaydb.core.internal.util.scanner.classpath.ClassPathResource.loadAsString(ClassPathResource.java:84)
at org.flywaydb.core.internal.resolver.sql.SqlMigrationResolver.scanForMigrations(SqlMigrationResolver.java:139)
at org.flywaydb.core.internal.resolver.sql.SqlMigrationResolver.resolveMigrations(SqlMigrationResolver.java:99)
at org.flywaydb.core.internal.resolver.sql.SqlMigrationResolver.resolveMigrations(SqlMigrationResolver.java:49)
at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.collectMigrations(CompositeMigrationResolver.java:122)
at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.doFindAvailableMigrations(CompositeMigrationResolver.java:104)
at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.resolveMigrations(CompositeMigrationResolver.java:90)
at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.resolveMigrations(CompositeMigrationResolver.java:43)
at org.flywaydb.core.internal.info.MigrationInfoServiceImpl.refresh(MigrationInfoServiceImpl.java:114)
at org.flywaydb.core.internal.command.DbValidate$2.call(DbValidate.java:164)
at org.flywaydb.core.internal.command.DbValidate$2.call(DbValidate.java:157)
at org.flywaydb.core.internal.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:75)
at org.flywaydb.core.internal.command.DbValidate.validate(DbValidate.java:157)
at org.flywaydb.core.Flyway.doValidate(Flyway.java:1280)
at org.flywaydb.core.Flyway.access$100(Flyway.java:71)
at org.flywaydb.core.Flyway$1.execute(Flyway.java:1176)
at org.flywaydb.core.Flyway$1.execute(Flyway.java:1168)
at org.flywaydb.core.Flyway.execute(Flyway.java:1650)
at org.flywaydb.core.Flyway.migrate(Flyway.java:1168)
at org.flywaydb.gradle.task.FlywayMigrateTask.run(FlywayMigrateTask.java:28)
at org.flywaydb.gradle.task.AbstractFlywayTask.runTask(AbstractFlywayTask.java:382)
Gradle Task:
// task that migrates the database
task migrateDb(type: org.flywaydb.gradle.task.FlywayMigrateTask) {
// parse hibernate config
def hibernateConfig = parseHibernateConfigByStageParameter()
// set config
url = hibernateConfig.url
driver = hibernateConfig.driver
user = hibernateConfig.username
password = hibernateConfig.password
locations = [ "classpath:${flywayDbPath}/${hibernateConfig.dbType}" ]
table = 'schema_version'
outOfOrder = true
ignoreMissingMigrations = true
}
Gradle dependency:
// dependencies
dependencies {
[...]
runtime project(':core:db:mysql')
[...]
}
During further testing I noticed that the error seems to be because of the Gradle Daemon. Adding --no-daemon to the migrateDb call works fine and doesn't trigger the error.
That's fine for me for now.
It turns out that I was deploying and old .war, which was built with some .sql files that were not around anymore.
Then I fixed this by running gradlew clean build

Resource injection in Spring Boot not working with gradle

I have a Configuration bean.
#Component
public class Config {
#Value("classpath:${app.file.name.srgbicc}")
public Resource icc;
#PostConstruct
void init(){
try {
tempdir = Files.createTempDir();
newIcc = copyIccFileToTemp();
}catch (IOException e){
throw new RuntimeException(e);
}
}
private File copyIccFileToTemp() throws IOException {
File tempIcc = new File(tempdir, icc.getFilename());
FileUtils.copyFile(icc.getFile(),tempIcc);
return tempIcc;
}
}
On icc.getFile() there is a FileNotFoundException
application.properties
app.file.name.srgbicc = sRGB.icc
I looked in my classpath and found the following situation:
build/classes/main (no icc file)
build/resources/main (icc file, application.properties)
When printed out my classpath during application start I only found ...myApp/build/classes/main.
No ../build/resources/main or ../src/main/resources entries there.
So I was wondering why is the resources not on the classpath?
according to http://docs.spring.io/spring-boot/docs/1.1.5.RELEASE/reference/htmlsingle/#build-tool-plugins-gradle-running-applications
this should be.
Of course if I put the icc file in build/classes/main its all working as expected, but it is not supposed to be there. right?
I tried to run the application with gradle run or gradle bootRun in intellij I use static main. The good thing is that the application fails consistently independent of how I start it.
My Project layout
myApp
src
main
java
pkg
Config.java
resources
sRGB.icc
application.properties
For the reference:
IntelliJ 13
spring-boot 1.1.5
Fgradle 2.0
Update
Here is a stripped down example of my code
https://gist.github.com/Vad1mo/bb5d23ca251341236fbd
I removed #PostConstruct in the config.init and run the application with gradle build all test are success when i rund from intellij the tests fail. this is strange that i know have different behavior
I solved the problem now.
What helped me was just to do a simple clean build and rebuild project in intellij. I was using to much eclipse and maven so I expected it to happen automagically.

JMS and ActiveMQ exception

I'm trying a project for school using JMS and ActiveMQ.
I copied the block of code from O'Reilly's books "Java Message Service 2nd Edition Jun 2009". It uses the publish and subscribe method and is in fact a small chat where everyone connected to the topic can send messages to everyone and everyone can see everyone else's messages. I compile the program and everything is ok, i try to run it and it gives me the following exception:
Exception in thread "main" javax.naming.NoInitialContextException: Cannot instantiate class: org.apache.activemq.jndi.ActiveMQInitialContextFactory [Root exception is java.lang.ClassNotFoundException: org.apache.activemq.jndi.ActiveMQInitialContextFactory]
I found that this problem might be because of 2 reasons:
activemq-all-5.2.0.jar is not added to classpath.
BUT added it the classpath (EnvironmentVariables->select ClassPath->Edit and add the following: "D:\Programming\JMS\ActiveMQ\apache-activemq-5.2.0" (THIS IS HOW YOU ADD IT NO?!?!)
jndi.properties file is not defined properly or has not been added to the classpath.
BUT i CREATED IT and added it's folder to the classpath. Here is what it contains:
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url = tcp://localhost:61616
java.naming.security.principal=system
java.naming.security.credentials=manager
connectionFactoryNames = TopicCF
topic.topic1 = jms.topic1
What is the problem? I have tried for ages to make it work. Am i doing something wrong? :(
Does the jndi.properties file path matter? or it only has to be placed in classpath and from here it can be found?
I also ran the activemq.bat from the bin folder D:\Programming\JMS\ActiveMQ\apache-activemq-5.2.0\bin\
[Edit]---------------------
So it works in Eclipse, BUT
Now i've properly added the .jar file in environment variables and i've run the client from windows's cmd. It doesn't give any errors, when i write in Eclipse's console, it appears in cmd console, everything ok, but when i try to write in cmd it gives an error at this line:
publisher.publish(message);
and it says
java.lang.NoSuchMethodError: org.apache.activemq.ActiveMQMessageProducerSupport.getDestination()Ljavax/jms/Destination;
Any ideas? I'd really like to be able to run it in CMD. :(
---------------------[/Edit]
Well I'm on Linux right now, but I bet it has to be:
D:\Programming\JMS\ActiveMQ\apache-activemq-5.2.0.jar
Also, if you run it with Eclipse and go to Project -> Build Path and this jar then there shouldn't be any problems. Anyhow can you post the CLASSPATH variable?
EDIT
I can't help you if you can't help me. This is related to any other future questions or work in general, provide details - it is always helpful. Will be much helpful if you would provide the EXACT command that you are running in CMD and the code of the class where this happens.
java.lang.NoSuchMethodError
generally it means that the jar is in place, class also, BUT the method is not. It happens when you compile with one version of the jar and at runtime provide a jar where this method was removed, thus the JRE can't find it throwing the error.
I just tested on my computer
I do not understand why it does not work for you, but it does for me. Here is my class:
package com.test;
public class Publisher {
public static void main(String[] args) {
try{
ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
ActiveMQSession session = (ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic destination = session.createTopic("FOO.TEST");
TextMessage textMessage = session.createTextMessage("Sample Payload");
TopicPublisher publisher = session.createPublisher(destination);
publisher.publish(textMessage);
session.close();
connection.close();
} catch(Exception e){
e.printStackTrace();
}
}
}
Everything is fine if I run it from eclipse with one single dependency in Maven:
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.2.0</version>
Then I do it with java and javac
javac -classpath /home/eugen/.m2/repository/org/apache/activemq/activemq-core/5.2.0/activemq-core-5.2.0.jar:/home/eugen/.m2/repository/javax/jms/jms/1.1/jms-1.1.jar Publisher.java
Notice that the only thing I added is the two jars.
Then java:
java -classpath /home/eugen/.m2/repository/org/apache/activemq/activemq-core/5.2.0/activemq-core-5.2.0.jar:/home/eugen/.m2/repository/commons-logging/commons-logging-api/1.1/commons-logging-api-1.1.jar:/home/eugen/.m2/repository/org/apache/camel/camel-core/1.5.0/camel-core-1.5.0.jar:/home/eugen/workspace/t/src/main/java/:/home/eugen/.m2/repository/javax/jms/jms/1.1/jms-1.1.jar:/home/eugen/.m2/repository/org/apache/geronimo/specs/geronimo-j2ee-management_1.0_spec/1.0/geronimo-j2ee-management_1.0_spec-1.0.jar com.test.Publisher
I added a few needed jars to the classpath and run it - it works perfectly.
Cheers, Eugene.
I ran into the same issue and it was a space (or what appeared to be a space) at the end of my property config.
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
Also note that you don't necessarily have to embed the jar file into your client code. Simply including the activemq-all as a maven dependency will work as well.

Resources