One useful feature that subversion and many other Versioning Systems offer for developers is the ability to include keywords in text files stored in the repository.
These keywords get replaced when some action is done on them by the server. This book excerpt (reproduced below) documents some keyword supported by subversion.
The keyword to be replaced is identified by an anchor in the text with the keyword name surrounded by two '$keywordName$.
Subversion defines the list of keywords available for substitution. That list contains the following five keywords, some of which have shorter aliases that you can also use:
LastChangedDate
This keyword describes the last time the file was known to have been changed in the repository, and looks something like $LastChangedDate: 2002-07-22 21:42:37 -0700 (Mon, 22 Jul 2002) $. It may be abbreviated as Date.
LastChangedRevision
This keyword describes the last known revision in which this file changed in the repository, and looks something like $LastChangedRevision: 144 $. It may be abbreviated as Revision or Rev.
LastChangedBy
This keyword describes the last known user to change this file in the repository, and looks something like $LastChangedBy: harry $. It may be abbreviated as Author.
HeadURL
This keyword describes the full URL to the latest version of the file in the repository, and looks something like $HeadURL: http://svn.collab.net/repos/trunk/README $. It may be abbreviated as URL.
Id
This keyword is a compressed combination of the other keywords. Its substitution looks something like $Id: calc.c 148 2002-07-28 21:30:43Z sally $, and is interpreted to mean that the file calc.c was last changed in revision 148 on the evening of July 28, 2002 by the user sally.
as in $keywordName$.
Have fun!
UPDATE on march/2009
Normally it would be necessary to set the properties on every single file of your system so the replacement of these props would happen. However, there is an easier way to do this, which is set the auto-props property in your environment.
In folder "C:\Documents and Settings\[your_username]\Application Data\Subversion" you will find a file named config (with no extension). In this file there should be a property "enable-auto-props" commented out. Remove the comment from this line so it looks like this:
### for 'svn add' and 'svn import', it defaults to 'no'.
### Automatic properties are defined in the section 'auto-props'.
enable-auto-props = yes
Then, on the same file, find the section [auto-props] and add a line at the end. If you want the replacement to happen only in your java files, add this:
Sunday, March 11, 2007
SVN Keywords
Posted by
Daniel
@
5:19 PM
0
comments
Labels: Subversion, Tools, Versioning
Monday, February 26, 2007
Install a jar file into maven's local repository
Sometimes, while using maven to build your projects, it is necessary to add a needed jar file directly into your local repository. This should not be a need if you have a remote repository correctly setup, but it might be useful if it is a too bureaucratic task or any other reason.
It is as simple as this. Having the file to be installed in your local repository in the local folder, issue the command below to install it.
mvn install:install-file -DgroupId=<MVN_GROUPID> -DartifactId=<MVN_ARTIFACTID> -Dversion=<MVN_VERSION> -Dpackaging=jar -Dfile=<JAR_FILE_TO_INSTALL>Could be useful! ;)
Posted by
Daniel
@
11:11 PM
1 comments
Sunday, February 11, 2007
Find the name of your session bean in JBoss
If you are writing JEE applications, you will most likely write a Session Bean to provide your View Tier with the services it need. This Session Bean is reached by the client application through a service called JNDI.
The problem is that each Application Server uses a different JNDI provider and this makes portability very hard to achieve. I wrote the code below to allow me to access the JNDI service and find my Session Bean. Please note that this would be much better placed in the container configuration file and not in the code, as it is here.
protected static Context getInitialContext( ) throws javax.naming.NamingException {
Properties p = new Properties( );
p.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
p.put(Context.URL_PKG_PREFIXES,"org.jboss.naming:org.jnp.interfaces");
p.put(Context.PROVIDER_URL, "jnp://localhost:1099");
return new javax.naming.InitialContext(p);
}
This method will return a
java.naming.Context object which can be used for the lookup on the service, like this:
PatientServices patientServices = (PatientServices)jndiContext.lookup("PatientBean/remote");
And how can you find the name under which your bean has been published on the application server? Well, in JBoss all you need to do is access the jmx-console (default URL is http://localhost:8080/jmx-console/). On the jboss session from this page, find the JNDIView service. Click on it and a new page will display on your browser.
On this new page there will be a java.lang.String list() MBean operation, and clicking on the invoke button the names of all available JNDI names will be shown on a tree-like structure which composes the name under which your Session Bean is registered on the JNDI service.
Posted by
Daniel
@
9:22 PM
2
comments
Maven Profiles
I was struggling with some different configuration files for my development and production environment. As a "weekend-free-time-developer-now-that-I-changed-into-management", my development environment is restricted. So I use the same instance of MySQL for the production database and run some tests on the same server with a different schema and configuration.
Using maven as a build/management tool improved my a lot my performance, but these different environments still gave me some headache. So I decided to leave laziness aside and configure some profiles in my pom files.
Maven profiles allow you to prepare different sets of configuration. There are for different types of profiles, defined in different files and with different purposes:
- Per Project: Defined in the POM itself (pom.xml).
- Per User: Defined in the Maven-settings (%USER_HOME%/.m2/settings.xml).
- Global: Defined in the global maven-settings (%M2_HOME%/conf/settings.xml).
- Profile descriptor: a descriptor located in project basedir (profiles.xml)
I decided to use the type number 1, which is a Per-Project configuration type, and unlike number 4 (which has a restricted scope) which is also a Per-Project configuration type it has the ability to change a lot of the project settings because it is in the same pom file as the projects' specifications themselves.
For starters, I wanted to have different jboss' data source xml files for production and development environments. As Maven works with a hierarchy of configuration files I figures the less intrusive way to set the build configuration was to have different folders for each environment. So where I previously had /src/main/resources/WEB-INF now I would have /src/main/resources/development/WEB-INF and /src/main/resources/production/WEB-INF. With the original single path, Maven did not need any special configuration to find my data source xml files (I love "convention over configuration"). With the 2 new folders, I had to add another layer to the hierarchy of Maven's configuration files and this layer would be the profiles.
In my pom.xml, I added a profiles section, obviously enough marked by the tag <profiles>. Here is what I added to my original pom.xml.
<profiles>
<profile>
<id>env-dev</id>
<build>
<resources>
<resource>
<directory>src/main/resources/development</directory>
</resource>
</resources>
</build>
<activation>
<property>
<name>env-dev</name>
</property>
</activation>
</profile>
<profile>
<id>env-prod</id>
<build>
<resources>
<resource>
<directory>src/main/resources/production</directory>
</resource>
</resources>
</build>
<activation>
<property>
<name>env-prod</name>
</property>
</activation>
</profile>
</profiles>
Now, you can tell maven to build based on different profiles. Where you normally would enter a command like
mvn install now you should change to:mvn install -P env-dev for development environment
OR
mvn install -P env-prod for production environmentAfter doing this, I was wondering... Which profile will maven choose to execute the build if I do not explicitly tell it?
That is very easy to check! Run the command:
mvn help:active-profilesIt will show you that there are no active profiles, but it will (wrongly IMHO) add BOTH (production and development) folders to your final build, and will not realize that those are actual resource folders.
One simple solution for this issue is to tell maven which profile should be used by default. I modified the profiles tag content to use the production environment as the default one, so this will force me during development to always add the
"-P env-dev" while I am testing/developing and this should make me used to always tell maven what I really want. The way to tell maven which one is the default active profile is in bold below. <profile>
<id>env-prod</id>
<build>
<resources>
<resource>
<directory>src/main/resources/production</directory>
</resource>
</resources>
</build>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>env-prod</name>
</property>
</activation>
</profile>
Now, if you run
mvn help:active-profiles again you will see that the env-prod is being used, which is the same as running mvn help:active-profiles -P env-prod.$ mvn help:active-profiles
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'help'.
[INFO] ----------------------------------------------------------------------------
[INFO] Building Fisio EJB Component
[INFO] task-segment: [help:active-profiles] (aggregator-style)
[INFO] ----------------------------------------------------------------------------
[INFO] [help:active-profiles]
[INFO]
Active Profiles for Project 'com.jc.fisio:fisio-ejb:ejb:0.1-SNAPSHOT':
The following profiles are active:
- env-prod (source: pom)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Sun Feb 11 18:13:13 BRST 2007
[INFO] Final Memory: 2M/5M
[INFO] ------------------------------------------------------------------------
Working with profiles is quite interesting, because it allows you to have multiple active profiles at the same time, providing a number of different combinations. It can be used to may purposes, like setting different application servers, web servers, snapshot version etc.
Posted by
Daniel
@
4:37 PM
6
comments
Tuesday, February 6, 2007
Setting Cygwin Bash Shell Looks
As I posted earlier, I like to use Cygwin as a *nix-like shell to use under Windows, because the command tool is IMHO terrible to use.
Cygwin has a lot of *nix functionalities which are not supported under windows default installation which forces you to install a big variety of software from different vendors.
Cygwin has its own port of bash shell, but on the default installation the looks are kind of dull. I use rxvt port for cygwin to start my shell and I used some configuration settings as suggested by this article.
So, with small changes to the suggestions of the author to have a larger buffer and the size of the started window I came with this .Xdefaults file. It shold be placed in your home directory.
! ~/.Xdefaults - X default resource settings
Rxvt*geometry: 120x60
Rxvt*background: #000020
Rxvt*foreground: #ffffbf
!Rxvt*borderColor: Blue
!Rxvt*scrollColor: Blue
!Rxvt*troughColor: Gray
Rxvt*scrollBar: True
Rxvt*scrollBar_right: True
Rxvt*font: Lucida Console-12
Rxvt*saveLines: 10000
Rxvt*loginShell: True
! VIM-like colors
Rxvt*color0: #000000
Rxvt*color1: #FFFFFF
Rxvt*color2: #00A800
Rxvt*color3: #FFFF00
Rxvt*color4: #0000A8
Rxvt*color5: #A800A8
Rxvt*color6: #00A8A8
Rxvt*color7: #D8D8D8
Rxvt*color8: #000000
Rxvt*color9: #FFFFFF
Rxvt*color10: #00A800
Rxvt*color11: #FFFF00
Rxvt*color12: #0000A8
Rxvt*color13: #A800A8
Rxvt*color14: #00A8A8
Rxvt*color15: #D8D8D8
! eof
Later I did another small change on the cygwin.bat file to use vim instead of vi as the default editor. The cygwin.bat file can be found on the installation directory of cygwin. Save the original file with another name and then replace it with the following content.
@echo off
C:
chdir C:\cygwin\bin
set EDITOR=vim
set VISUAL=vim
set CYGWIN=codepage:oem tty binmode title
rxvt -e bash --login -iNow when you start cygwin, the shell window will look like the one on the right (click on it to see a larger version). Play around with the collor definitions on the .Xdefaults file to have a setup that pleases you. .Xdefaults gives a lot of possibilites and you can see some examples here, here and here.
Posted by
Daniel
@
3:55 AM
1 comments
Sunday, January 28, 2007
Using Apache as a Proxy for Tomcat Applications
I spent the day trying some configurations to make the integration between Apache HTTP Server and Tomcat.
The configuration that worked best for me basically was to setup a VirtualHost in Apache as a proxy with the same name as the application in Tomcat engine. As a resume, below tou will find some of the steps I went through and what I changed in the configuration files (I am using Apache 2.2 and Tomcat 5.5).
In Apache it is necessary to enable the mod_proxy Module and setup a NameVirtualHost. The httpd.conf (found in %APACHE_HOME%/conf) configuration file should be changed as below.
#Uncomment or add the lines below into the general session of your httpd.conf file.
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
# Add the Virtual Host for your application at the end of the file
NameVirtualHost *
<VirtualHost *>
ServerAdmin serveradmin@domain.com
DocumentRoot "C:/java/Tomcat5.5/webapps/"
ServerName myapplication.domain.com
ServerAlias *.myapplication.domain.com
ProxyPass /foo-app http://localhost:8080/foo-app
ProxyPassReverse /foo-app http://localhost:8080/foo-app
</VirtualHost>
After setting this file in your apache server, restart it and proceed to configuring the Tomcat Server, by editing the server.xml file (found in %CATALINA_HOME%/conf). Simply add the lines below at the end of the file, but inside the <server> tag.
<Service name="Tomcat-Apache">
<Engine name="Apache" defaultHost="myapplication.domain.com" debug="0">
<Host name="myapplication.domain.com" debug="0"
appBase="c:/java/Tomcat5.5/webapps/foo-app"
unpackWARs="true" autoDeploy="true">
<Context path="/foo-app" docBase="c:/java/Tomcat5.5/webapps/foo-app" debug="1" reloadable="true"/>
</Host>
</Engine>
</Service>
Now, open your browser and type the URL http://myapplication.domain.com/foo-app and you should be redirected to your application after passing by Apache and Tomcat.
Tomcat RMI Unmarshalling Exception
This is one of those posts that shows how frustrating sometimes the developer job can be! :)
I had a WAR component that was delivered successfully and worked fine in Jetty 6.0 rc2, but the same WAR file would not work under Tomcat 5.5. This application uses some session beans that are available in my JBoss Server. When I tried to execute the lookup() command in my client application running in Tomcat I had an exception thrown:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: java.net.MalformedURLException: no protocol:
Then I asked: Why? Why does it work in Jetty like a charm? Reading ahead at the message of the exception I noticed the MalformedURL message included this: "5.5/temp/0-fisio-web-1.0-SNAPSHOT/WEB-INF/classes/" which made me realize that this was just part of the full URL where my Tomcat Server was running. Searching through the net I found this post, which led me to this other post (and there is also this other post on this subject).
For my surprise this is a known bug since JDK 1.2, marked as WON´T FIX by SUN! Is it unbelievable or not??
There is a workaround suggested by Sun that says that one should usefile.toURI().toURL()
instead of file.toURL()
but many times, this is not in our hands, as is my case because Tomcat is taking care of this for me, so unless me (or some other generous soul) change and test (and do a backward compatibility test which seems to be what is frightening SUN into not changing this behavior) this way of implementing the RMI communication, the best thing to avoid this problem is to install all your applications in a path that does not include white spaces or illegal characters.