Tag Archives: xml

从Twitter等看企业软件架构(一)

企业软件发展到现在,普遍面临的一个问题是自身积重难返。系统功能越来越多,数据存储到处都是,技术标准五花八门。几乎任何一个做实施的都头痛每天遇到的各种历史遗留问题。事情就是这样,企业软件已经是一个构造复杂的精密系统,无数的管道线路纠结在一起,牵一发而动全身,难以为继。

问题

看一下业务流程管理技术趋势图:

image

摆在面前的当务之急就是SOA化的系统结构,然而,除了在政府机构有比较好的案例意外,其他行业鲜有成功的事实,原因又在哪里呢?不负责任的分析一下,至少有以下几点:

对庞大的现有系统改造成本巨大,SOA是需要一个规模效应的,当系统间不断的整合才能发挥其低耦合的结构特,在此之前的投入往往会被看成是不值得的,这里有一个门槛效应。

业务和技术要求高,SOA不仅是一个技术课题,也是一个业务课题。当前大多数机构和组织的设计能力还不能达到全面应用的要求。软件架构往往在分布式和集中式之前博弈,分布式的高要求往往让很多项目选择折中的方案。“二步提交”等分布式系统特有的技术问题带来的风险考验开发人员的能力和系统的综合管理能力。

规格差异化,各厂商为了自己的利益,推广各自的方法论,互相之间缺乏沟通,壁垒明显,势必造成技术推广的困难。

巨大的挑战面前是巨大的市场,SOA默默挣扎了这么多年,依然坚挺,其背后是非常不错的理论架构。

一种思路

其实说穿了,SOA无非就是解决系统整合的方式,互联网是分布式系统的基础,而Web2.0是内容和服务整合最成功的例子。

翻开Twitter, FriendFeed, Facebook的API文档,绝对找不到一个ESB,SOA的名词,能看到的无非是JSON, XML, RSS, ATOM,或者单独说个REST。但是解决的问题和SOA是一样的,系统整合,标准协议,高可用性,服务寻址等等。但他们看起来很不规范。从某种意义上说,属于SCA(Service Component Architecture)的理念。

image

SCA与SOA最大区别就是给服务实现松绑,很多实现不需要再去应用个别高端厂商发明的WS-*,可以更灵活的应用互联网上被验证有效的方式。SCA保留了SOA理念中的核心,更加强调组件的概念,弱化技术性的限制。SCA是个非常复杂的主题,这里是一个相对容易理解的SCA白皮书

比较一下几种格式,或许能看得更清楚:

数据格式可读性数据转换扩展性开发难度
SOAP较差,所有格式中最复杂的较容易,可以根据定义生成类型可扩展,有一定难度很高
XML看设计能力需自定义转换规则任意扩展/或利用命名空间较高
JSON清晰易懂没有类型定义,在强类型端处理困难任意扩展,缺少规则简单
RSS/ATOM比较清晰RSS多种不同版本,ATOM相对统一一些,整体来说较简单通过命名空间扩展一般
YAML可读性最好可以容易的序列化与反序列化任意扩展,缺少规范简单

 

从以上比较不难看出,单纯从开发和功能上讲,新的YAML最有优势,也容易继续改良取长补短。而标准最多的SOAP实在是有点笨重,难以和新格式竞争。

未完待续

Maven need to act as Wikipedia

Central Repository is an revolution of Open Source. Now we have a unique, global software artifact standard (although not officially). It’s amazing.

The next question is How to Make it Right.

In the most situation, we cannot request an Open Source Authors take the responsibility to maintain their product to the eternity. We cannot assurance that everybody can understand and use Maven in exactly right way either. Maven is still far away from 1-click use software. And the infrastructure of the distribution system of Maven Artifact Repository is even more complex.

Maven is a collaborating system since everyone has the right to commit their own work. But Maven is lack of collaboration functionality. The POM.xml need to be corrected by other who is more familiar with Maven; the source code need to be uploaded; dependencies on unnecessary artifact should be set to optional…. all those actions need to be well tracked and synchronized around the world. It’s much more difficult since it a distribution system.

Wikipedia is the most greatest thing in the age of Web 2.0. So Maven would learn a lot from the success model.

Technorati 标签: ,

Java:利用XML生成Word文档

Word 2003后提供了一种xml的文档格式。可以利用这一点方便的生成doc文档

Word 2007更完全使用xml与数据压缩包的方式存储,使得用类似的方法处理附件也变为可能。

相关demo下载 doc-creator

概述

实现步骤如下:

  1. 定义Word文档样式,存为xml文档。
  2. 定义数据xml格式,生成样本数据。
  3. 修改word文档样式xml文件,制作xsl模板文件。
  4. 编程实现:数据->xml数据->模板转换->doc文档

创建模板

打开Word文档,另存为:Word 2003 xml格式。

使用xsl编辑器 (如 Stylus Studio)或手工编辑,创建XSL模板 。

   

   

相关XSL问题可以参考 http://www.w3schools.com/xsl/

利用dom4j处理相关xml操作

下面是一些基础实现方法

    /*
     * (non-Javadoc)
     *
     * @see cn.ccb.sarm.bizprocess.assetdeal.exam.approve.bizservice.IWfConferenceBS#writeXML(java.io.OutputStream,
     *      cn.ccb.sarm.bizprocess.assetdeal.exam.approve.common.bo.TaskVO,
     *      java.util.List, cn.ccb.sarm.common.model.bo.WfConferenceBO,
     *      cn.ccb.sarm.common.model.bo.WfConfBpBO)
     */
    public void writeXML(OutputStream output, TaskVO task, List opinionList, WfConferenceBO conf,
            WfConfBpBO confBP) throws IOException, IllegalAccessException,
            InvocationTargetException, NoSuchMethodException {
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("conference");
        Element taskNode = root.addElement("task");
        addBeanProp(task, taskNode);
        Element confNode = root.addElement("conferenceInfo");
        addBeanProp(conf, confNode);
        Element confBpNode = root.addElement("confBPInfo");
        addBeanProp(confBP, confBpNode);
        Element approveNode = root.addElement("approvers");

        addListMapEntry(opinionList, approveNode);

        XMLWriter writer = new XMLWriter(output);
        writer.write(doc);

    }

    /**
     * 转换list对象为多个元素
     *
     * @param list
     *            对象list
     * @param node
     *            父节点
     */
    private void addListMapEntry(List list, Element node) {
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Map map = (Map) it.next();
            Element approveNode = node.addElement("approver");
            addMapEntry(map, approveNode);
        }
    }

    /**
     * 转换bean为xml
     *
     * @param bean
     *            对象bean
     * @param node
     *            父节点
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     */
    private void addBeanProp(Object bean, Element node) throws IllegalAccessException,
            InvocationTargetException, NoSuchMethodException {
        Map propMap = BeanUtils.describe(bean);
        addMapEntry(propMap, node);
    }

    /**
     * 转换map对象为xml
     *
     * @param map
     *            数据对象
     * @param node
     *            父节点
     */
    private void addMapEntry(Map map, Element node) {
        Set entrySet = map.entrySet();
        Iterator it = entrySet.iterator();
        while (it.hasNext()) {
            Map.Entry e = (Entry) it.next();
            node.addElement(e.getKey().toString()).addText(
                    (e.getValue() == null ? "" : e.getValue().toString()));
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see cn.ccb.sarm.bizprocess.assetdeal.exam.approve.bizservice.IWfConferenceBS#transformDocument(java.io.OutputStream,
     *      java.io.FileInputStream, java.io.FileInputStream)
     */
    public void transformDocument(OutputStream out, InputStream data, InputStream template)
            throws TransformerException {
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transform = factory.newTransformer(new StreamSource(template));

        Result result = new StreamResult(out);
        transform.transform(new StreamSource(data), result);
    }

测试代码

    public void testWriteXML() throws Exception {
        IWfConferenceBS conferenceBS = new WfConferenceBS();
        TaskVO task = new TaskVO();
        task.setBizTypeName("测试业务类型");
        List opinionList = new ArrayList();
        Map m = new HashMap();
        m.put("userName", "testUser");
        m.put("userConfRole", "testUserRole");
        m.put("approverOpinion", "approverOpinion");
        m.put("lastChangeTime", "time");
        opinionList.add(m);
        WfConferenceBO conf = new WfConferenceBO();
        conf.setConfPlace("place");
        WfConfBpBO confBP = new WfConfBpBO();
        confBP.setConfResult("testResult");
        confBP.setConfOpinion("confOpinion");
        File tempOutputFile = File.createTempFile("specialApproveTemp", ".xml");
        OutputStream output = new FileOutputStream(tempOutputFile);
        conferenceBS.writeXML(output, task, opinionList, conf, confBP);
        output.flush();
        output.close();

        OutputStream out = new FileOutputStream(File.createTempFile("specialApproveTemp", ".doc"));
        File template = ResourceUtils
                .getFile("classpath:cn/ccb/clpm/wf/common/specialApproveTemplate.xsl");
        conferenceBS.transformDocument(out, new FileInputStream(tempOutputFile),
                new FileInputStream(template));
        output.flush();
        output.close();

    }

Spring 2.5 AOP Schema编程小解

AOP是已经是蔓延了好几年的话题,不过因为没有标准化的平台以及工具的缺乏,一直没有很好的推广。这里所用的AOP实现主要是Spring对AspectJ的封装。感谢Spring的出色贡献,我们甚至都不用知道什么是AspectJ就可以使用AOP概念进行程序设计和实现了。

AOP编程模型

通常情况下,程序中有很多公共的部分,比如事务控制,比如LOG记录。他们遍布程序各处,使代码凌乱不堪难以维护。AOP是对OOP一个很好的补充。OOP很好的描述了业务模型中各个组件的交互方式,但是对于系统组件的装配与互操作,却鲜有明确的定义。

下面就是这样的一个应用场景,对于一个业务方法,比如queryUserInfo我们都需要事务控制,日志记录。

从业务方法角度看AOP

AOP  Example 1

在每一次调用业务方法时,AOP框架会使用around方式调用装配给业务方法的adviser..(可能更好理解的方式是类似 beforeMethod, afterMethod…)。

从Adviser看AOP

image

一个Adviser可能被装配给多个业务类的多个方法,通过不同的操作模型完成相关任务。

Spring 2.5 与AOP实现

下面通过一个非常简单的例子来说明Spring中AOP的Schema配置实现方式。

在此之前,应当对Spring 2.5 的Schema机制以及AOP AspectJ编程的一般概念有所了解。

请先阅读

下面是AOP的配置spring bean xml 文件


http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	
		
		
			
			
			
			
			
			
			
			
		
	
	
	
	

	
		
		
		
		
			
		
	

	
	
	


下面是 org.ave7.ws.aop.SystemMonitor 类的实现代码

package org.ave7.ws.aop;

import org.aspectj.lang.ProceedingJoinPoint;

import org.apache.commons.collections.LRUMap;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.lang.time.DurationFormatUtils;
import org.apache.commons.lang.time.StopWatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class SystemMonitor {

    private static final LRUMap logMap = new LRUMap(100);

    // 参数call包含了被调用方法的相关信息,请参考ApectJ网站
    public Object profileMethod(ProceedingJoinPoint call) throws Throwable {
        Log log = obtainLogger(call.getTarget().getClass());
        if (log.isDebugEnabled()) {
            log.debug("call " + call.getSignature().toLongString());
            log.debug("with para: "
                    + ReflectionToStringBuilder.toString(call.getArgs(),
                            ToStringStyle.MULTI_LINE_STYLE, true));

            StopWatch watch = new StopWatch();

            watch.start();

            try {
                Object rt = call.proceed();

                log.debug("return : "
                        + ReflectionToStringBuilder.toString(rt,
                                ToStringStyle.MULTI_LINE_STYLE, true));
                return rt;
            } catch (Throwable e) {
                log.warn("exception: " + e.getMessage(), e);
                throw e;

            } finally {
                watch.stop();
                log.debug("executing time: "
                        + DurationFormatUtils.formatDuration(watch.getTime(),
                                "m:s.S"));

            }
        } else {
            return call.proceed();
        }

    }

    private Log obtainLogger(Class clazz) {

        Log log = (Log) logMap.get(clazz);
        if (null == log) {
            log = LogFactory.getLog(clazz);
            logMap.put(clazz, log);
        }
        return log;
    }

}