解惑

解己之惑,解人之惑

分类:Java (第5页共20页)

Java技术

很难统一

呵呵,开始搞项目的事情了,发现项目的很多东西,大家的经验不一样,很难统一。

首先就是IDE,由于我们去之前架构师就给这边的经理发了一些原型系统的需求,要求建立Intellij的工程,但是我们四个开发人员三个都不熟,这边的经理也不熟,经理原来一直用NetBeans,我们三个用Eclipse,只有另外一个人和架构师用Intellij,不过既然架构师要求,还是得先用Intellij。

然后就是工程的目录,还不知道公司有没有统一的要求,不过已经有其它的项目了,而且我们的项目还要基于一些已有的其它项目,估计应该和他们靠齐,这个业界也是没有统一的意见。

最后就是选用的一些项目开发的其它东西,例如工程编译,经理建议用Maven,不过架构师最开始的需求里面是要求用Ant,然后源代码管理,现在SVN很流行,但是这边在用Perforce,这个东西不免费,据说还很贵,还有就是这个原型的UI用什么?原来的一些前期的工作也做了一些,开始用Google的GWT,后来又用Flex,这个原型现在在用JSP,以后用什么还不确定。

由此可见Java的东西,真的是很难统一,没有一个完全的标准,当然,有更多的选择总是好的。

看的东西太多也容易忘啊

前段时间面试的时候问到的一个问题,实现一个线程安全的计数器,我已经让类变成Singleton了,set方法也变成同步的了,这个时候面试的人问,如果这个程序是工作在多CPU的机器上,发现这个计数器仍然存在计数不准确的情况会是因为什么?我的回答是:JDK的bug,呵呵,面试的人说不是,JDK提供了修正的机制,就是把计数的那个变量标记为volatile,这样就可以防止,今天有空搜索了下这个关键字,发现我以前翻译的一个文章《破除java神话之三:原子操作都是线程安全的》说的就是这个问题,虽然不是完全匹配,但是机制就是这样的,多处理器有各自的寄存器,所以可能有问题,使用volatile关键字就可以让JVM在读写那个变量的时候都从主存读写,而不在本地保存副本。

Terracotta和Hyperic

其实还没有真正用过,这个是美国那边准备采用的第三方组件,Terracotta用来做集群的,号称Network-Attached Memory,国内好像没有太多介绍的,目前就看到javaeye和Infoq上的两个介绍文章。而Hyperic是用来监控服务器状态的,当然可以监控集群状态下的Web服务器的各个节点的详细状况和信息。由于还没有真正使用过,不好多说什么了,有兴趣的可以研究下。

Class has two properties of the same name

开发Web Service并不是很难,但是没有好的例子,网上的一些例子都过于简单,做一个DEMO样的可以跑起来的Web Service确实不难,但是要开发一个真正实用的还是需要花些功夫的。
这个是最近遇到的一个问题,原因就是那些需要Model的Annotation使用不当,在类上面使用了XmlAccessType,然后在getter上也使用了XmlElement,在使用stub的方式作为客户端的时候没有问题,但是使用JAX-WS的方式调用的时候就出现标题中的错误。
这个问题解决后,调用没有问题,也能返回一个对象,但是对象的所有属性全部为null,需要继续解决。
到目前位置,已经使用了下面的Client方式,或多或少存在问题,只有使用stub的方式最好(根据wsdl生成代码)

  • JaxWsProxyFactoryBean,调用成功,但是返回对象为空,和直接的JAX-WS一样
  • ClientProxyFactoryBean,调用失败,Service的方法的名称加了Annotation定义,但是从生成的SOAP信息看,是使用的arg0,arg1这样的形式,所以到Server端以后参数都为null,调用失败
  • 直接JAX-WS(javax.xml.ws.Service),和第一个一样

CXF2.0.8+Spring+Hibernate

丢在这里备忘,也给大家一个参照,费了一些劲才配好的。
阅读全文

CXF2.1.1有问题

开始搞Web Service,用了CXF,下载了2.0.8和2.1.1,开始弄的是2.1.1,发现有问题:

java.lang.NoSuchMethodError: org.jaxen.BaseXPath.<init>(Ljava/lang/String;Lorg/jaxen/Navigator;)V

怎么也发布不成功,后来修改成2.0.8,发现可以了,通过浏览器访问什么的都没有问题,然后从wsdl生成stubs后,运行unit test有问题:
java.lang.IncompatibleClassChangeError
    at org.apache.cxf.wsdl11.WSDLServiceBuilder.copyExtensionAttributes(WSDLServiceBuilder.java:120)
    at org.apache.cxf.wsdl11.WSDLServiceBuilder.buildServices(WSDLServiceBuilder.java:228)
    at org.apache.cxf.wsdl11.WSDLServiceBuilder.buildServices(WSDLServiceBuilder.java:153)
    at org.apache.cxf.wsdl11.WSDLServiceFactory.create(WSDLServiceFactory.java:117)
    at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:138)
    at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:129)
    at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:55)
    at javax.xml.ws.Service.<init>(Service.java:57)
 
唉,步履维艰啊

2008年8月21日更新:
发现这些都是Classpath搞的,因为原来的工程中也包含了老版本的Web  Service的包,我们这个工程在原来的工程里面,但是我发布的时候没有包含原来的jar,但是Eclipse工程里面是依赖的,所以Server运行没有问题,在Eclipse跑单元测试的时候有问题。

2.1.1的问题是DOM4J.JAR搞的,里面也包含了jaxen的类,把那些类从jar包里面去掉问题解决

开始研究Web Service

新的项目其实是转向Web Service的,公司的整体架构将采用SOA,本来这一阶段只是个临时阶段,但是Web Service的任务要提前开始了,因为另外一个新的项目需要使用我们的Service,而现在的这个项目是基于一个老的项目,只使用EJB2,所以在原来的项目的EJB3和Web Service可以根据Annotation自动发布的基础设施都不存在了,而且架构师打算弃用JBoss,转向Tomcat,所以现在最简单的方案就是基于Axis自己写必须的东西了,还不是很清楚,要慢慢研究了。

Dynamic Proxy的异常处理

现在越来越感觉Dynamic Proxy是个好东西,不过发现异常处理还是得注意下,因为调用实际的代码返回的异常都会被包一次成为InvocationTargetException,所以如果你想让原本的异常继续往上抛,那么必须捕获异常并且得到targetException然后再抛出去:
        try {
            result = targetMethod.invoke(targetObject, args);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("IllegalAccessException", e);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("IllegalArgumentException", e);
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        }

增加一个方法要修改多少个地方?

被调到新的项目组,理论上算个Team Leader,没有真正的转正,老大最开始跟我说这边的事情我可以做主,但是美国那边有个架构师开始搭了个架子,意思是在这个架子的基础上做,试了下,发现很繁琐,为了增加一个方法,得修改好多个类。这个阶段其实是个过渡阶段,以后我们会使用Web Service,所以我们哟定义Web Service的接口,然后因为是过渡阶段,所以提供了EJB2的过渡方案和原来的系统整合,所以还得改Remote接口,Local接口可以直接从Service接口extends一下就行了,然后得修改Service的实现类,加上原先的架子里面,设计的是Service里面的每个public方法对应一个Operation类,这些类设计成Command模式,方便以后可以更好的进行负载的Dispatch,就这样,给Service增加一个接口,要完全实现得至少修改3个类,增加一个类,而且前两天也提过这个项目使用的Annotation的一个好处,但是这样一来,我要实现那个接口,也得在Finder里面增加方法。最终,我得修改4个类,增加一个类来增加一个Service接口。天啊,这个是我最讨厌的。

下周打算修改这个架子,取消EJB2的临时方案,使用Dynamic Proxy实现Service,同时可以引人Transaction(这个方案原来也用了,但是架构师以Transaction的问题否决了,那个时候还没有想到怎么解决Transaction的问题,前天突然想起来我的EJB单元测试框架就是用的自定义Transaction的),同时也抛弃Finder的那个方案,因为其实我的BaseOperation已经提供了进行Hibernate的查询的方便的基础功能。最重要的是Finder中定义的Query如果有问题的话修改后不能Hot Deploy,如果在Operation的方法体里面的修改就可以Hot Deploy。这样修改后,增加一个接口只需要修改Service然后增加一个Operation类实现就行了,只要改两个地方。

Annotation的一个很好的用处

加入另外一个项目获得的最大的好处就是这个了,他们定义了一些Annotation,然后定义一些Finder接口,接口里面只定义方法,但是不用实现,使用Dynamic Proxy实现接口实现方法参数和Query中的参数自动绑定,赞一个。这样写Hibernate的Query就很简单了,只需要定义基本的东西就行了。

更早的文章 更新的文章

© 2025 解惑

本主题由Anders Noren提供向上 ↑