Spring Set Production / Development level JDBC properties - spring

I have a JDBC.properties file that contains db connection information
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.databaseurl=jdbc:mysql://127.0.0.1/mydb
jdbc.username=root
jdbc.password=
Now when I use it in the server my info changes
jdbc.username=root
jdbc.password=mypassword
What I do now is manually change this information before making war file and upload it to the server.
Now I was wondering if there is any way I could set this information so that i don't have to change this information every time before upload
How to do this??

Don't put your properties inside your war file. Externalize them. Put them somewhere in a well known path (/etc/myapp/jdbc.properties).
You shouldn't be creating different artifacts for your production,development and test environment. It should be the same. Recreating the artifact means a new version which (in theory) means new testing. Even if you use maven profiles.
The approach I tend to use is to put some defaults in an internal properties file and optionally load a file from outside the war. That way you provide your users with the possibility to override the default configuration.
<context:property-placeholder location="classpath:/jdbc.propertes,file:/etc/myapp/jdbc.properties" igonre-resource-not-found="true" />
That way your defaults are inside the application and users can override it by specifying other properties in the /etc/myapp/jdbc.properties file.

You could use spring profiles. This blog post should give you the idea: http://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/

You should use a build tool like Maven and do this with resource filtering and profiles.
Doing it through Spring profiles is probably one way, but in my opinion it makes more sense to be handling it through the build.
Consider the following with Maven:
src/main/resources/jdbc.properties:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.databaseurl=${jdbc.databaseurl}
jdbc.username=${jdbc.username}
jdbc.password=${jdbc.password}
pom.xml:
<project ...>
...
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
...
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<jdbc.databaseurl>jdbc:mysql://127.0.0.1/mydb</jdbc.databaseurl>
<jdbc.username>username</jdbc.username>
<jdbc.password>password</jdbc.password>
</properties>
...
</profile>
<profile>
<id>prod</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<jdbc.databaseurl>jdbc:mysql://212.123.45.6/mydb</jdbc.databaseurl>
<jdbc.username>username</jdbc.username>
<jdbc.password>secret-password</jdbc.password>
</properties>
...
</profile>
</profiles>
...
</project>
For development, invoke:
mvn clean package ... -Pdev
Likewise for production:
mvn clean package ... -Pprod
Maven filtering allows you to replace properties in your .properties resources based on properties defined in Maven via <properties/> (either in a profile, or not).
References:
- Resource filtering
- Profiles

Related

Maven. Build only module that have deploy profile

Context:
I have a rather large system with several maven module formed in a hierarchy. When I need to develop I can go to the root and build using a specific profile -Pdeploy
The problem with this is that, my entire project is built (which takes a while) when I only in truth need to build a dozen lightweight modules that just deploy.
How should I got into improving the team's efficiency when deploying?
Basic Idea: You may not skip building modules but you may skip some of your plugin executions contained.
Usually your repository will already have build module artifacts present, so the overall speed should already be better once a previous build have been run and module artifacts can be pulled from there.
The idea is that you add a profile setting that defines skip-properties according to what you may want to omit when doing a deploy profile build only.
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault />
</activation>
<properties>
<skip.documentation>false</skip.documentation>
<skip.sign>false</skip.sign>
<skip.sources>false</skip.sources>
<skip.checks>false</skip.checks>
<skip.reports>false</skip.reports>
<skip.installer>false</skip.installer>
</properties>
</profile>
<profile>
<id>deploy</id>
<properties>
<skip.documentation>true</skip.documentation>
<skip.sign>true</skip.sign>
<skip.sources>true</skip.sources>
<skip.checks>true</skip.checks>
<skip.reports>true</skip.reports>
<skip.installer>true</skip.installer>
</properties>
</profile>
</profiles>
Your pom than might contain
<plugin>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${version.maven-checkstyle-plugin}</version>
<configuration>
<skip>${skip.checks}</skip>
</configuration>
</plugin>
This method can be applied on a project pom level (pluginDependencies) or overridden in each module.

Can Maven ask the user for values and enter them into a file?

I have a lot of config files that values have to change in. I would like to know if someone runs the "package" command can it ask for some values and insert them into my project files?
Better Approach would be have different property/config file depending upon environment.
Prod
Dev
Keep the two set of values in two different file. At times specify the file name.
For 90% of build tasks, there's Maven. For everything else, there's maven-antrun-plugin.
I suggest creating a custom ant script (which can be embedded in your pom.xml) that prompts for user input and writes out your config files using the Ant Input Task
You can use maven -P to select a maven profile and in turn selec the property files for it.
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<resource.prefix>dev</resource.prefix>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<resource.prefix>prod</resource.prefix>
</properties>
</profile>
</profiles>
Now access your resource file as ${resource.prefix}_config.properties. So when the profile is prod, the resource file prod_config.properties will be taken.
You cannot really make maven prompt for input unless you do some ant stuff suggested by noahz.
What you can do if you don't want to play around with Profiles is to use properties in your pom file.
Example:
<project>
<groupId>abc</groupId>
<artifactId>def</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<myProperty>someValue</myProperty>
</properties>
<build>
<plugins>
<plugin>
...
<configuration>
<outputDir>${myProperty}</outputDir>
</configuration>
</plugin>
</plugins>
</build>
</project>
You can use the property wherever you want within the pom file and you can even use the property when filtering resources.
The property could be empty by default and then have a new value set from command line:
mvn package -DmyProperty=anotherValue
And the anotherValue would be propagated to wherever it is used in pom.
You can read about Maven Resource Filtering here.
If you place a file in src/main/resources it could be filtered with the above property:
src/main/resources/important-stuff.properties
some.nice.property = Nice!
some.variable.property = ${myProperty}
And this should be added to the pom:
<build>
...
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
The filtered important-stuff.properties would end up in target/classes and in the jar and look like this:
some.nice.property = Nice!
some.variable.property = anotherValue
Resource filtering is really handy.

Maven, how to disable by profiling the copying of one resource by the war plugin?

Inside a maven project with some resources configured like this :
<webResources>
....
<resource>
<directory>${project.build.directory}/${temp.dir}</directory>
</resource>
</webResources>
the ${temp.dir} is generated conditionally by a plugin and do not exists always. When it is not there maven of course fail with an NPE, how could I fix this ?
I'm not sure if I understand what your problem (exactly) is, but it seems to me that Maven profiles could help you:
http://maven.apache.org/guides/introduction/introduction-to-profiles.html
In your case, probably you need profile activation on property existence, like this:
<profiles>
<profile>
<activation>
<property>
<name>temp.dir</name>
</property>
</activation>
...
</profile>
</profiles>

Maven: filtering seam components.xml in target directory

I'm trying to convert an Ant project to Maven. The existing build uses Ant-style properties in src/main/webapp/WEB-INF/components.xml, which is a Seam file.
I'm able to get the properties expanded in the actual resulting war file, via the maven-war-plugin. But I can't seem to get the properties expanded in target/myproject/WEB-INF/components.xml.
This means that when I try to run the Jetty plugin, it doesn't see the expanded properties.
I tried defining the properties in both an external file, and also right in the build. My profile section looks like the following:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<filters>
<filter>src/main/filters/components-dev.properties</filter>
</filters>
</build>
<properties>
<debug>true</debug>
<jndiPattern>FOO</jndiPattern>
</properties>
</profile>
</profiles>
When you run mvn jetty:run it executes the lifecycle up through test-compile. The web resources don't get filtered until the war plugin runs as part of package. I found a question on stackoverflow that seems similar, does that solution work for you?

What is the best way to parameterize a Maven script to switch between Spring configurations?

What is the best way to parameterize a Maven script to switch between Spring configurations?
I have Maven building a WAR file for a web app. I have alternative spring configurations - one for integration testing with mock objects, one for live production use with real objects.
Ideally, I would like to have one Maven build script that can build either WAR file. At present, I just hack the spring config file before building, commenting in and out the mocks and real objects.
What is the best way to go about this?
I suggest that you use the build profiles.
For each profile, you will define a specific Spring configuration:
<profiles>
<profile>
<id>integration</id>
<activation>
<activeByDefault>false</activeByDefault>
<property>
<name>env</name>
<value>integration</value>
</property>
</activation>
<!-- Specific information for this profile goes here... -->
</profile>
<profile>
<id>production</id>
<activation>
<activeByDefault>false</activeByDefault>
<property>
<name>env</name>
<value>production</value>
</property>
</activation>
<!-- Specific information for this profile goes here... -->
</profile>
...
You will then activate one profile or the other by setting the parameter env : -Denv=integration for the first profile, -Denv=production for the second profile.
In each profile block, you can specify any information specific to your environment. You can then specify properties, plugins, and so on. In your case, you may change the configuration of the resources plugin in order to include the adequate Spring configuration. For example, in integration profile, you can specify where Maven will search the Spring configuration file:
<profile>
<id>integration</id>
<activation>
<activeByDefault>false</activeByDefault>
<property>
<name>env</name>
<value>integration</value>
</property>
</activation>
<build>
<resources>
<resource>/path/to/integration/spring/spring.xml</resource>
</resources>
</build>
</profile>

Resources