I'm trying to create an empty database using liqubase. I use this approach to do this, but the problem is it doesn't work for me.
I use Postgresql 10 and there are my configurations for maven and liqubase:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.0.5</version>
<configuration>
<propertyFile>src/main/resources/liquibase/liquibase.properties</propertyFile>
</configuration>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
And my liqubase.properties:
changeLogFile=src/main/resources/liquibase/db.changelog.xml
driver=org.postgresql.Driver
dropFirst=false
url=jdbc:postgresql://localhost:5432/auth?createDatabaseIfNotExist=true
username=postgres
password=root
The error on mvn clean package is:
org.postgresql.util.PSQLException: FATAL: database "auth" does not
exist
Liquibase will not create a database that does not exist at all. I also imagine that the url parameter ?createDatabaseIfNotExist=true that is referenced in the linked question/answer is probably MySql specific.
This is slightly beyond the scope of your question, but you could use liquibase against a Docker postgres instance, and per the docker-library's documentation on ENVIRONMENT VARIABLES, set POSTGRES_DB to "auth" (in your case), and it will create the "auth" db when the docker image launches, with which liquibase can then interact.
Related
I'm using asciidoctor-maven-plugin and asciidoctor-diagram to generate PlantUML diagrams (more specifically C4-PlantUML diagrams). When generating those diagrams, output is polluted by these kind of messages
[Log] "dynamic undefined legend colors" requires PlantUML version >= 1.2021.6, therefore only static assigned colors are used
I tracked them down to asciidoctor-diagram embedding - in its source, lo less, a reasonably old version of PlantUML (see their Github source).
Fortunatly, there is in asciidoctor-diagram plantuml converter.rb class some code to use PlantUML provided externally through an environment variable named DIAGRAM_PLANTUML_CLASSPATH.
But as I use asciidoctor-diagram through asciidoctor-maven-plugin, how can I set that environment variable from my Maven POM without setting it in the maven launch ? Indeed, I want to use a dependency from my pom and maven-dependency-plugin properties goal to have it correct on any machine without configuration.
I've already tried using asciidoctor-maven-plugin configuration attributes, but it didn't seem to work.
Is there any other way to inject environment variables into asciidoctor-maven-plugin ?
EDIT 1 I've also tried using the properties-maven-plugin to add the environment variable to my maven build this way
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>Set DIAGRAM_PLANTUML_CLASSPATH from PlantUML maven dependency PATH</id>
<phase>process-resources</phase>
<goals>
<goal>set-system-properties</goal>
</goals>
<configuration>
<properties>
<property>
<name>DIAGRAM_PLANTUML_CLASSPATH</name>
<value>${net.sourceforge.plantuml:plantuml:jar}</value>
</property>
</properties>
</configuration>
</execution>
</executions>
</plugin>
But it changed nothing
EDIT 2
So, after some reflection, I had to resolve to use the age-long solution : debugging the culprit code (in this case, asciidoctor-maven-plugin).
In AsciidoctorMojo#execute(), in a long chain of calls, we initialize a JRuby interpreter (in JRubyAsciidoctor#createRubyRuntime).
When creating this interpreter, we pass the system environment. This system environment DO NOT include my DIAGRAM_PLANTUML_CLASSPATH variable, so I guess the properties-maven-plugin does not really set it as environment variable for the whole maven build - or there has been some changes in recent maven versions.
However, this JRubyAsciidoctor#createRubyRuntime method accepts as input a map of environment variables. Can we manipulate it ? Absolutely not as it is a private method.
And guess what ? DIAGRAM_PLANTUML_CLASSPATH doesn't appear in the list because it's not an environment variable, but a system property, which is quite different.
So the question is more "how can I create an environment variable ? Or inject an environment variable in my ruby env prior to running my build ?"
So, I've established in the question that what was not working was the injection of the environment variable into JRuby : As default, Java doesn't allow setting environment variable, and on the other hand asciidoctor only allow injection through environment variable. So I had to create that environment variable.
Hopefully, Stackoverflow already answers that question : How do I set environment variables from Java?.
My only point was doing that in a maven build. Enter GMaven Plus. Using this plugin the following way
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<executions>
<execution>
<id>Put PlantUML path in that damn DIAGRAM_PLANTUML_CLASSPATH environment variable</id>
<phase>initialize</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<scripts>
<script>${project.basedir}/src/build/groovyScripts/set_PlantUML_path_in_system_environment.groovy</script>
</scripts>
</configuration>
</execution>
</executions>
</plugin>
Notice the preliminary call to dependency-maven-plugin to obtain all dependencies paths as properties.
THen I created a very small Groovy script
log.debug "PlantUML dependency path is ${project.properties['net.sourceforge.plantuml:plantuml:jar']}"
setEnvironmentVars(['DIAGRAM_PLANTUML_CLASSPATH':project.properties['net.sourceforge.plantuml:plantuml:jar']])
And it was enough to have asciidoctor-maven-plugin working.
CAVEAT: I'm quite sure this won't work with recent Java releases like Java 14 and Java 17. Anyway, in Java 11, it works!
I need to deploy my project into artifactory. For this purpose I use maven-assembly-plugin together with artifactory-maven-plugin
only I can use for building of mvn is this CMD (small updates are possible):
mvn -e -B -U clean deploy -DskipIntegrationTests=false -DskipCoverageReport=false -Dservice_name=sample_service
What I can not do in mvn command is update service name. It will be always "sample_service" or some other constant which represent name of service
Because I do not know name of service (there could be more services) my base part of pom.xml looks like this (artifactId is created dynamically from property service_name):
<groupId>my.group.id</groupId>
<artifactId>${service_name}</artifactId>
<version>2.0.0-SNAPSHOT</version>
The problem is that parameter -Dservice_name will always consists "underscores". Because of conventions artifact has to consists "dashes" instead of "underscores".
Is there any way (some plugin for instance) how I can do something like this?
<groupId>my.group.id</groupId>
<artifactId>${service_name}.replaceAll("_","-")</artifactId>
<version>2.0.0-SNAPSHOT</version>
In short for property service_name I need replace underscores by dashes before building of artifact.
Thanks for answers.
This cannot be done.
Properties used inside <artifactId> can only be set through the command line. You have no chance to manipulate them in Maven. The only chance I see is to change the command line, so that you do the replacement before you send the parameter to Maven.
I found a solution for my problem. But I am not sure if it is correct way how to solve it. I used plugin gmaven-plugin
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<executions>
<execution>
<phase>pre-clean</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
project.getModel().setArtifactId(project.properties["service_name"].replaceAll('_', '-'))
project.getArtifact().setArtifactId(project.properties["service_name"].replaceAll('_', '-'))
</source>
</configuration>
</execution>
</executions>
</plugin>
After that I use maven-assembly plugin which upload data into artifactory. And this plugin read artifact id from instance "project.getArtifacts()" so I update it directly.
So I updated artifact id directly in maven instance.
As I say it is not 100 percent correct but in my case it helps
You can do this with the buildhelper plugin, it has a goal regex-property which can set a property based on an initial value (your service_name property) and a regular expression to replace with a replacement value.
Example from the usage page (adapted because the value used made no sense):
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>regex-property</id>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>human.version</name>
<value>${project.version}</value>
<regex>-SNAPSHOT</regex>
<replacement> pre-release development version</replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
I have a POM file which includes a property (under properties section) which has an IP value that we use when pushing it to git.
<device.ip>1.2.3.4</device.ip>
But for my builds, I need to use a another IP value, so I should change it to my required IP when I start to work on a new branch.
I'd like to be able to check the variable value at build startup and abort it given the variable value is different from what I need.
Any other solutions also welcomed.
(I hope my question would not be downgraded because of lack of code - there is no really code to write here. The scenario is quite self explanatory)
Than you for your advice.
You could use the maven-enforcer-plugin which support such checks.
The usage looks like this for the requirePropery rule.
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M2</version>
<executions>
<execution>
<id>enforce-property</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireProperty>
<property>device.ip</property>
<message>You must set a device.ip property!</message>
<regex>.*\d.*</regex> <!-- Express the value you need. -->
<regexMessage>The device.ip property contain...</regexMessage>
</requireProperty>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
I would suggest splitting your project in modules.
Module 1 contains your code without any configuration.
Module 2 refers to module 1 and additionally contains what goes into production. For multiple deployments create an additional module for each. This is where your production property goes.
Module 3 refers to module 1 (but not 2) and contains whatever you need for development (configuration like this property and helper classes). For complex scenarios make an additional module for each.
This has worked well for me.
I would like to specify some system properties in my applicatio (deterined at compile time).
I am using the spring boot maven plugin to compile
Currently, according to this questions: Specify system property to Maven project
I tried the following setup (however this does not work as it is for a different plugin)
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>application.boot.AppStarter</mainClass>
<systemProperties>
<systemProperty>
<name>application.version</name>
<value>${application.version}</value>
</systemProperty>
<systemProperty>
<name>release.date</name>
<value>${timestamp}</value>
</systemProperty>
</systemProperties>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
How can i specify the properties in this plugin?
Java system properties which you add are only accessible by the process they are added to.So even if you manage to add some system properties during the Maven build, it will no longer be there when the build is done.
What will happen if you distribute your jar to someone else. How do you expect these properties to be available?
Solution
Refer this post to see how to access the artifactId and version at runtime
In a similar fashion you can add the timestamp entry as well to the src/main/resources/project.properties
buildTimestamp=${timestamp}
timestamp is not a pre-defined property like project.version or project.artifactId.So you will have to set extract the timestamp from the Maven property ${maven.build.timestamp} and set it as value to your timestamp property. This is already answered in this question.
I am thinking of using a template engine to generate the web.xml and other things.
Is there as way to to run a java file or a script before the maven install command? Or before the war is generated.
I am not sure what the phase should be, but basically before anyone else looks at the web.xml so I can touch it to make a new valid one.
You can use the exec-maven-plugin to run either a program/script (using the exec goal) or a Java program (using the java goal).
The phase immediately before package is prepare-package (see the Default lifecycle in the Lifecycle Reference), so you could use that. But you might prefer to generate the web.xml earlier in the lifecycle (even as early as generate-resources).
Putting these together, you might try something like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.2</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>your_packaging_script</executable>
<!-- optional -->
<workingDirectory>/tmp</workingDirectory>
<arguments>
<argument>--some-option</argument>
</arguments>
</configuration>
</plugin>
Alternatively, you might consider writing your own plugin, especially if you think the idea would be useful for more than one project.