Maven搭配Ant,使构建过程更灵活

Maven使构建变得规范、简便,但在某些时候还是感觉Ant更容易控制,把两者结合起来使构建变得更加灵活。Maven所定义的构建模型,再加上一些Plugin的帮助,让我们每容易的实现两者的结合。下面看个例子。

一个例子

项目中遇到这样一个问题,程序要检查某种License,License的版本号在另外的配置文件中定义。基于安全考虑,最好把版本号在编译期就写到某个常量中,而不在运行期读取某配置文件。假设我们要把版本号写入到某个enum类型的常量里,之前我们可以准备它模块文件。所以基本的构建流程如下:

  • 准备源文件
    • 读取License版本号
    • 读取Java模版文件
    • 版本号替换
    • 生成Java源文件包含最新的版本号
  • 编译源文件
  • 测试
  • 打包

实现

先看如下的代码目录结构(所用代码都在Github上)。

Selection_003

  • ant_replace_license_version.xml是Maven将要调用的Ant脚本
  • ant-contrib-1.0b3.jar包含了很多ant的扩展,有很多非常Powerful的工具。在这个例子中我会使用loadfile, propertyregex等功能。
  • License.template是License.java的模板文件
  • pom.xml是maven脚本
  • version.h是一个C/C++的头文件,里面定义了VERSION

构建过程就是要把version.h里版本号取出,替换模板文件里的占位符,然后生成真正的License类,并放到包com.innoli.sample中,由App调用。

具体文件内容

version.h

License.template

ant_replace_license_version.xml

使用了ant-contrib的扩展,完成了读取、查找、替换、生成新的类文件等工作。

pom.xml

使用了exec-maven-plugin来调用ant脚本,也可以使用Apache Maven AntRun Plugin, 但它MS使用了很旧的ant。在process-resources阶段,生成License类。

 

编译

一切就是这么简单!

About “Plug-in from Existing JAR Archives” kind projects in maven+tycho build

In Eclipse RCP project, you may need to create such kind of “Plug-in from Existing JAR Archives” projects, because you need to reuse non-OSGi jar, such as Google Guava, SLF4j and etc.

In our team, before we have to manually download the needed jar libs from website, then change build.properties, MANIFEST.MF. And of couse, these libraries should be uploaded to version control system (such as P4, Git), as others (as well as Jenkins) can sync to latest and build.

This approach has some defects:

  • Too much manual work and hard to maintain the dependencis.
  • 3rd party libs become more and more.

Here is a solution for that – using maven dependency:copy-dependencies to copy all needed libs.

tycho + maven

Tycho is a great maven plugin, which can help to do headless build for a Eclipse RCP project. It will analyze the dependencies in MANIFEST.MF and also in pom.xml. We can use the feature to define the 3rd party dependencies in pom.xml.

You can find more usefule information about tycho on Eclipse.com.

Define the needed libraries in pom.xml

Just as what a common maven project does, you can define the libraries you need in <dependencies> of pom.xml, such as,

Use maven-dependency-plugin:copy-dependencies to copy

Use the goal of maven-dependency-plugin:copy-dependencies to copy those jars to specific folder, such as,

The goal is defined at “initialize” phase.

Change MANIFEST.MF

With this pom.xml, you can do a manually build and retrieve the jars from maven repository. Then you need to put them into the bundle’s CLASSPATH and exported packages in MANIFEST.MF.

Summary

Using this way, you don’t need to worry about third party libraries in OSGi environment any more. All dependencies are defined in pom.xml. It’s very clean and clear. Of course, in real world, you need do more configuration in pom.xml (such as clean work) and an IDE environment integration.

 

 

在Maven构建环境中使用第三方Jar包

在Maven开发中,有时不能避免要使用到第三方Jar包,这些包在Maven Repo里找到不到。如何解决呢?

有两种方法。

第一种:安装到Maven Repository里。

这样lib.jar会被安装到Maven的本地Repo里,坐标就是org.yli.lib:lib1:jar:1.3。在使用它的POM里就可以写:

这种作法的缺点就是还不够灵活。除非把包安装到内部的Maven服务器上,不然团队统一就需要都安装相同的包。

第二种:使用<scope>system</scope>

如果没有内部的Maven服务器,但有个第三方包,团队可以从代码服务上下载到本地,我们可以通过设置<scope>system</scope>属性来设置dependency.

如果你是一个多Module工项,project.basedir对于每个Project都不一样,但我们可以把这些依赖放到Parent Module里的dependencyManagement里,这样其他的Sub Module就可以不用再设置具体信息了。

当使用Maven遇到”resolution will not be reattempted until the update interval of MyRepo has elapsed”的解决办法

当你部署了一个私有的Maven Repo,然后release/snapshots里库被更新了,就有可能遇到标题上的错误。

网上有一种解决办法,就是修改setting.xml里的updatePolicy设置,比如:

把updatePolicy改成always, 就没有这个问题了。

还有一种办法就是在命令行上加上-U的选项,有一样的效果。下面有一些说明。

  • -U,–update-snapshots Forces a check for updated releases and snapshots on remote repositories
  • -up,–update-plugins Ineffective, only kept for backward compatibility

 

JBoss+Maven+Cargo开发EJB的Hello World!

Team要使用EJB了,不再使用以前比较山寨的CGI+Google Protocol; 同时构建工具也变成了Maven。这几天做了些实验,想写一个最简单的Hello World。有一个EJB的Service,再有一个Client去使用这个服务。

几天下来有点小崩溃,相对EJB 3的教程来说,配置实在太麻烦,有太多的属性、参数、版本要做了。好在最后取得了成功,记在这里做个小结。

1. 工具的安装

Maven 3

从Apache的网站上下载,然后把${MAVEN_HOME}/bin目录加到系统的PATH下。

JBoss AS

我这里下载的是JBoss AS 7.1.1.Final压缩包。这里的版本非常重要,它和之后开发的其他包有依赖关系。

假设JBoss被解压到${JBOSS_HOME}下。

NOTE: 解压之后一定在JBoss的bin下运行add-user.bat,安装一个管理用户。这个很重要。

2. 写一个EJB的服务

写一个简单EJB服务很简单,我们可以有Maven的archetype生成一个工程的框架。

一路回车之后,就得到了一个Server的工程文件夹结构。但删掉默认生成的App.java和AppTest.java.

然后在org.yli.learn.server中,加入两个类。一个是接口SayHello,一个是EJB Bean类SayHelloBean.

里面用到一些EJB 3的Annonation,大家自己查查书吧。

下一步就是修改pom.xml文件了,这里我们只要加入一些编译的依赖就行。

然后你可以编译安装了。

3. EJB Bean的部署

我选择了Cargo来部署Bean到JBoss里,好像有一个plugin叫jboss-as的,也可以做一样的事情。

我们只要在pom.xml加上:

然后就可以用mvn的goal来部署和运行JBoss了

  • 部署: mvn cargo:deployer-deploy
  • 运行: mvn cargo:run或cargo:start

好了,这样我们写好的EJB就部署到了JBoss的容器中。

4. EJB的Client

这部分的配置有点让我的崩溃,花的时间也最多。

基本步骤也是先用maven建立一个框架,比如我们的工程是org.yli.learn:client:jar:1.0, 包名是org.yli.learn.client.

我们在包里有一个Client,它会去向JBoss获取service并使用。

POM文件里有相关的依赖

然后你可以用mvn clean package来编译打包了。

很重要的一点,就是要添加一个properties文件。在src/main下面,建立一个resources的文件夹,然后在里面新建文件jboss-ejb-client.properties. 我这里使用的是一些默认的选项,具体文档在JBoss的Confluence里有介绍。

好了,可以用mvn exec:exec来运行了!

你可以顺利看到Hello, Jason!

真太不容易了!但现在的感觉很爽啊! 😀