Why Load Balance not work in Hessian C# client calling to hessian service?

November 9, 2011 by · Comments Off on Why Load Balance not work in Hessian C# client calling to hessian service?
Filed under: design, java, troubleshooting 

When I was migrating our application from C# to Java, our Java service moved ahead of  the client application. The client application is in C#. And we export service through Hessian service. So we call java hessian service through C# hessian client.

But we met a big problem on load balance after the new application deployed. The load is never balanced on the C# hessian client’s request. The service is invoked through F5.

After digging into the code of C# hessian, I found the cause: C# Hessian Client uses HttpWebRequest with default properties to call java hessian service, while the default HttpWebRequest’s KeepAlive property is true. That means after the C# client connected to a load balance server, it will keep on calling the same back-end service and the request from this client will not routed to other back-end service.

So the solution is to change the default KeepAlive property in file CHessianMethodCaller.cs

HttpWebRequest req = webRequest as HttpWebRequest;

req.KeepAlive = false;  // newly added line to assure load balance work

 

Digg This
Reddit This
Stumble Now!
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

3 method to evaluate expressions in Java

August 7, 2011 by · Comments Off on 3 method to evaluate expressions in Java
Filed under: java 

The problem: You need to evaluate dynamic expression in your java code. Some common situation includes on a program contest evaluation system, on a dynamic business logic control,  on evaluation of dynamic math expression, or even on evaluation of test case.

There is many ways evaluate expression. These methods can be categorized into 3 different ways generally.

Method 1. Leverage dynamic compilation in Java.

You can add the dynamic expressions to codes of a skeleton class  template; and then compile the class.  It is the most original and flexible way to evaluate expressions. For full instructions see my last post:

3 steps to dynamically compile, instantiate and run a Java class.

Method 2. Evaluate expressions by java libraries.

There’s dozens of libraries to evaluate expression in java. The most intuitive and powerful library should be jexl and expressionoasis.

http://commons.apache.org/jexl/

http://code.google.com/p/expressionoasis/

When evaluating expressions, JEXL merges an Expression with a JexlContext. An Expression is created using JexlEngine#createExpression(), passing a String containing valid JEXL syntax. A simple JexlContext can be created by instantiating a MapContext; a map of variables that will be internally wrapped can be optionally provided through its constructor. The following example, takes a variable named foo, and invokes the bar() method on the property innerFoo:

// Create or retrieve a JexlEngine
JexlEngine jexl = new JexlEngine();
// Create an expression object
String jexlExp = "foo.innerFoo.bar()";
Expression e = jexl.createExpression( jexlExp );

// Create a context and add data
JexlContext jctx = new MapContext();
jctx.set("foo", new Foo() );

// Now evaluate the expression, getting the result
Object o = e.evaluate(jctx);

Method 3. Evaluate expression by scripting engine

You can evaluate expression in your java code by scripting engine supported by Java platform. You are free to script the expressions in your favorite language.  To show all available scripting engines in your system:

    private static void availableEngine()
    {
        ScriptEngineManager mgr = new ScriptEngineManager();
        List<ScriptEngineFactory> factories = mgr.getEngineFactories();
        for (ScriptEngineFactory factory : factories)
        {
            System.out.println("ScriptEngineFactory Info");
            String engName = factory.getEngineName();
            String engVersion = factory.getEngineVersion();
            String langName = factory.getLanguageName();
            String langVersion = factory.getLanguageVersion();
            System.out.printf("\tScript Engine: %s (%s)\n", engName, engVersion);
            List<String> engNames = factory.getNames();
            for (String name : engNames)
            {
                System.out.printf("\tEngine Alias: %s\n", name);
            }
            System.out.printf("\tLanguage: %s (%s)\n", langName, langVersion);
        }
    }

By default, JavaScript engine is included in JVM. So you can write expression in javascript with java variable support, and evaluate it in java code. Example code:

    private static void jsEvalWithVariable()
    {
        List<String> namesList = new ArrayList<String>();
        namesList.add("Jill");
        namesList.add("Bob");
        namesList.add("Laureen");
        namesList.add("Ed");

        ScriptEngineManager mgr = new ScriptEngineManager();
        ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");

        jsEngine.put("namesListKey", namesList);
        System.out.println("Executing in script environment...");
        try
        {
          jsEngine.eval("var x;" +
                        "var names = namesListKey.toArray();" +
                        "for(x in names) {" +
                        "  println(names[x]);" +
                        "}" +
                        "namesListKey.add(\"Dana\");");
        }
        catch (ScriptException ex)
        {
            ex.printStackTrace();
        }
    }

You can also script in groovy, ruby, python… Groovy can be well integrated with jvm, let’s take groovy as an example.  Firstly include groovy 1.7.10 in pom file if you’re using maven ( or include groovy engine jar groovy-engine.jar in the classpath of the project if not using maven).

  <dependency>
  	<groupId>org.codehaus.groovy</groupId>
  	<artifactId>groovy</artifactId>
  	<version>1.7.10</version>
  </dependency>

Secondly write scripts in groovy, and finally evaluate them by ScriptEngine.

It is a common practice to access java variables and objects in you expressions only if you binds the variables/objects to your script engine object. You can evaluate expression in your groovy engine like this:

    private static class Position
    {
        private int x;
        private int y;
        public Position(int x, int y)
        {
            super();
            this.x = x;
            this.y = y;
        }

    }

    //require(jar:'groovy-engine.jar')
    // or include any version of groovy 1.7.10 or above in your pom file
    private static void groovyEval()
    {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("groovy");

        if(null==engine)
        {
            System.err.println("Could not find groovy script engine,make sure to include groovy engine in your classpath");
        }
        try
        {
            // basic groovy expression example
            System.out.println(engine.eval("(1..10).sum()"));

            // example showing scripting with variables (object method invoking)
            engine.put("first", "HELLO");
            engine.put("second", "world");
            System.out.println(engine.eval("first.toLowerCase() + second.toUpperCase()"));

            //example with boolean expression
            engine.put("m", 3);
            engine.put("n", 9);
            System.out.println(engine.eval("m<n"));

            //example with variable object and object member access:
            Position pos = new Position(100, 200);
            engine.put("p", pos);
            System.out.println(engine.eval("p.y-p.x>0"));
        }
        catch (ScriptException e)
        {
            e.printStackTrace();
        }
    }

Finally, if you just want to evaluate and debug complicated math expression, Math Expression Evaluator may help:

http://www.beyondlinux.com/blog/handy-utilities/math-expression-calculator/

 

Digg This
Reddit This
Stumble Now!
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Json and flexjson on exchanging abstract object data

August 7, 2011 by · 1 Comment
Filed under: java 

JSON is a lightweight text-based open standard designed for human-readable data interchange.  It is widely used in java applications as a replacement of XML. Many times we need to convert java object to json text and vice versa.

You can use Gson to convert java object to JSON format, and convert JSON into java object. And you can export your interface by JSON RPC using jsonrpc4j or json-rpc.

public class Employee
{
    private String name;
    private int salary;
    private String dateOfBirth;

    public static void main(String[] args)
    {
        Employee emp = new Employee();
        emp.setName("david");
        emp.setDateOfBirth("20080801");

        Gson gson = new Gson();
        String jsonString = gson.toJson(emp, Employee.class);
        System.out.println(jsonString);
    }
}

The output would be:

{“name”:”david”,”salary”:0,”dateOfBirth”:”20080801″}

Now you can deserialize the jsonString to an Employee object.

   Employee employee = gson.fromJson(jsonString, Employee.class);
   System.out.println(employee.getName());

The problem with Gson is that it loses the type information on serialization, and you need to provide type information explicitly on deserialization like the above example.

How to serialize and deserialize with automatic type recognization?

Flex Json is the answer. FlexJson would add a “class” attribute in the serialized json string to represent the full qualified class name. Thus you can exchange interface/abstract object by json format. Here’s an example.

        JSONSerializer serializer = new JSONSerializer();
        String empString = serializer.serialize(emp);
        System.out.println(empString);

        JSONDeserializer<Object> deserializer = new JSONDeserializer<Object>();

        Employee eee = (Employee) deserializer.deserialize(empString);
        //System.out.println(eee);

The output would be like this:

{“class“:”com.beyondlinux.demo.bean.Employee”,”dateOfBirth”:”20080801″,”name”:”david”,”salary”:0}

Reference List:

http://en.wikipedia.org/wiki/JSON-RPC

http://code.google.com/p/jsonrpc4j/

http://code.google.com/p/json-rpc/

http://flexjson.sourceforge.net/

Digg This
Reddit This
Stumble Now!
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

How to enable remote JMX support on tomcat

July 21, 2011 by · Comments Off on How to enable remote JMX support on tomcat
Filed under: java 

We need to monitor tomcat by jconsole and visualvm for check memory/thread/object usage of tomcat when problem occur. So I tried to enable JMX support on tomcat by modify the catalina.sh by some suggest online (in one line, for windows, “export” should be replaced by “set”):

export JAVA_OPTS="-Dcom.sun.management.jmxremote.port=8086
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false"

And connect successfully to tomcat by jconsole on local machine. But failed to connect tomcat on remote machine.

In fact, to enable remote access of JMX, you need to specify the server hostname such as:

export JAVA_OPTS="-Dcom.sun.management.jmxremote.port=8086
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Djava.rmi.server.hostname=192.168.32.12"

Note: the hostname could not be 0.0.0.0 to represents any server name. For windows, should use “set” instead of “export”. 

Digg This
Reddit This
Stumble Now!
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

3 steps to dynamically compile, instantiate and run a Java class

July 20, 2011 by · 2 Comments
Filed under: java 

The background:  sometimes we need to compile dynamic source code, and run the code.  Some common situation includes on a program contest evaluation system, on a dynamic business logic control,  on evaluation of dynamic math expression, or even on evaluation of dynamic expression on test case.

Here’s 3 steps to implement compilation, instantiation and running of dynamic java source code.  It is the hard way,  the most original and elastic way; cause you can add any logic in the generation of your dynamic source code.

1. Construct an in-memory java source file from your dynamic code.

You need to override SimpleJavaFileObject, and take a string content as and In memory java source file.

2.Compile your files by JavaCompiler

You need to compile by JavaCompiler which could be got by ToolProvider.getSystemJavaCompiler(). Then get a task of JavaCompiler.CompilationTask. And call the task to execute compilation.

3.Load your class by URLClassLoader

Load your class by URLClassLoader from classes output folder, then instantiate a instance from the class, and finally call method of the class from the instance by reflection.

Here’s a complete working code (tested on JDK 1.6):

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Locale;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

/**
 * Dynamic java class compiler and executer  <br>
 * Demonstrate how to compile dynamic java source code, <br>
 * instantiate instance of the class, and finally call method of the class <br>
 *
 * http://www.beyondlinux.com
 *
 * @author david 2011/07
 *
 */
public class DynamicCompiler
{
    /** where shall the compiled class be saved to (should exist already) */
    private static String classOutputFolder = "/classes/demo";

    public static class MyDiagnosticListener implements DiagnosticListener<JavaFileObject>
    {
        public void report(Diagnostic<? extends JavaFileObject> diagnostic)
        {

            System.out.println("Line Number->" + diagnostic.getLineNumber());
            System.out.println("code->" + diagnostic.getCode());
            System.out.println("Message->"
                               + diagnostic.getMessage(Locale.ENGLISH));
            System.out.println("Source->" + diagnostic.getSource());
            System.out.println(" ");
        }
    }

    /** java File Object represents an in-memory java source file <br>
     * so there is no need to put the source file on hard disk  **/
    public static class InMemoryJavaFileObject extends SimpleJavaFileObject
    {
        private String contents = null;

        public InMemoryJavaFileObject(String className, String contents) throws Exception
        {
            super(URI.create("string:///" + className.replace('.', '/')
                             + Kind.SOURCE.extension), Kind.SOURCE);
            this.contents = contents;
        }

        public CharSequence getCharContent(boolean ignoreEncodingErrors)
                throws IOException
        {
            return contents;
        }
    }

    /** Get a simple Java File Object ,<br>
     * It is just for demo, content of the source code is dynamic in real use case */
    private static JavaFileObject getJavaFileObject()
    {
        StringBuilder contents = new StringBuilder(
                                                   "package math;"+
                                                            "public class Calculator { "
                                                           + "  public void testAdd() { "
                                                           + "    System.out.println(200+300); "
                                                           + "  } "
                                                           + "  public static void main(String[] args) { "
                                                           + "    Calculator cal = new Calculator(); "
                                                           + "    cal.testAdd(); "
                                                           + "  } " + "} ");
        JavaFileObject so = null;
        try
        {
            so = new InMemoryJavaFileObject("math.Calculator", contents.toString());
        }
        catch (Exception exception)
        {
            exception.printStackTrace();
        }
        return so;
    }

    /** compile your files by JavaCompiler */
    public static void compile(Iterable<? extends JavaFileObject> files)
    {
        //get system compiler:
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        // for compilation diagnostic message processing on compilation WARNING/ERROR
        MyDiagnosticListener c = new MyDiagnosticListener();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(c,
                                                                              Locale.ENGLISH,
                                                                              null);
        //specify classes output folder
        Iterable options = Arrays.asList("-d", classOutputFolder);
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager,
                                                             c, options, null,
                                                             files);
        Boolean result = task.call();
        if (result == true)
        {
            System.out.println("Succeeded");
        }
    }

    /** run class from the compiled byte code file by URLClassloader */
    public static void runIt()
    {
        // Create a File object on the root of the directory
        // containing the class file
        File file = new File(classOutputFolder);

        try
        {
            // Convert File to a URL
            URL url = file.toURL(); // file:/classes/demo
            URL[] urls = new URL[] { url };

            // Create a new class loader with the directory
            ClassLoader loader = new URLClassLoader(urls);

            // Load in the class; Class.childclass should be located in
            // the directory file:/class/demo/
            Class thisClass = loader.loadClass("math.Calculator");

            Class params[] = {};
            Object paramsObj[] = {};
            Object instance = thisClass.newInstance();
            Method thisMethod = thisClass.getDeclaredMethod("testAdd", params);

            // run the testAdd() method on the instance:
            thisMethod.invoke(instance, paramsObj);
        }
        catch (MalformedURLException e)
        {
        }
        catch (ClassNotFoundException e)
        {
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception
    {
        //1.Construct an in-memory java source file from your dynamic code
        JavaFileObject file = getJavaFileObject();
        Iterable<? extends JavaFileObject> files = Arrays.asList(file);

        //2.Compile your files by JavaCompiler
        compile(files);

        //3.Load your class by URLClassLoader, then instantiate the instance, and call method by reflection
        runIt();
      }
}
Digg This
Reddit This
Stumble Now!
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Speed up your eclipse as a super fast IDE

June 25, 2011 by · 57 Comments
Filed under: java 

Follow these steps to speed up your eclipse as a super fast IDE , it works for 32 & 64 bit version eclipse/jdk on my windows 7 x64.

1.Disable antivirus software, or add your jdk & eclipse & workspace & other related folder to white list in your antivirus software.

2.Disable unecessary validations and startup action in eclipse reference.

For validations: on eclipse menu Windows -> Preferences -> Validation, click “Disable All”, and then select the validator which you need. I selected “Classpath Dependency Validator” only.

For startup action: on eclipse menu Windows -> Preferences, type “startup”, select “Startup and Shutdown”, untick the options you don’t need. (Thanks for David’s suggest,  I’ve added the above 2 detail steps for readers)

3.Modify eclipse.ini to set the Xmn(new generation size), Xms and Xmx, enable parallel GC
-vm
C:/jdk1.6.0_25/bin
-startup
plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar
–launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.100.v20110502
-product
org.eclipse.epp.package.jee.product
–launcher.defaultAction
openFile
–launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
–launcher.XXMaxPermSize
256m
–launcher.defaultAction
openFile
-vmargs
-server
-Dosgi.requiredJavaVersion=1.5
-Xmn128m
-Xms1024m
-Xmx1024m
-Xss2m
-XX:PermSize=128m
-XX:MaxPermSize=128m
-XX:+UseParallelGC

4.Create a ram disk(virtual disk) on memory, and put your jdk on the ram disk.
You can use imdisk to create ram disk. Firstly download it from: http://www.ltr-data.se/opencode.html/#ImDisk,  and install it.

Then set the ImDisk driver to auto-load at Command Prompt with administrative privileges (for example right-click, start as Administrator), type:

sc config imdisk start= auto
net start imdisk

create a 200m ram disk as driver n by:
imdisk -a -t vm -s 300m -m n:

then you should format the ram disk manually.

later ,if you would like to remove the ram disk, just run the command:
imdisk -D -m n:

5.Make sure you are using sun jdk, not open jdk/gcj nor other jdk on linux.
If you are not satified with the after the above steps, install jrockit instead of sun jdk, and change some of the vm options by jrocket specification,
jrockit is faster than sun jdk.

Some note:

On my laptop(Aspire 4745G 4G mem ), windows 7 x64, by default, it takes more than 30 seconds to start eclipse.  After the vm options tuned,  takes only 15 seconds.

And after jdk moved to ram disk, it takes 10 seconds to startup.

Digg This
Reddit This
Stumble Now!
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

maven打包web项目时同时打包为war和jar文件

June 9, 2011 by · 2 Comments
Filed under: java 

首先在pom.xml文件中指定war的打包方式,war

然后在pom文件的plugins节点下面增加如下内容即可mvn package时同时生成war, jar包。为了 mvn package install, mvn package deploy能够同时部署jar包,我们增加了后面2节点的配置:

<!--  package jar on package -->
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <executions>
  <execution>
    <id>make-a-jar</id>
    <phase>compile</phase>
    <goals>
      <goal>jar</goal>
    </goals>
  </execution>
  </executions>
</plugin>
<!--  install jar to local repository -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<packaging>jar</packaging>
<artifactId>${project.artifactId}</artifactId>
<groupId>${project.groupId}</groupId>
<version>${project.version}</version>
<file>
${project.build.directory}/${project.artifactId}-${project.version}.jar
</file>
</configuration>
</execution>
</executions>
</plugin>
<!--  deploy jar to remote repository -->
<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-deploy-plugin</artifactId>
 <executions>
 <execution>
 <phase>deploy</phase>
 <goals>
  <goal>deploy-file</goal>
 </goals>
 <configuration>
 <packaging>jar</packaging>
 <generatePom>true</generatePom>
 <url>${project.distributionManagement.repository.url}</url>
 <artifactId>${project.artifactId}</artifactId>
 <groupId>${project.groupId}</groupId>
 <version>${project.version}</version>
 <file>${project.build.directory}/${project.artifactId}.jar</file>
 </configuration>
 </execution>
 </executions>
</plugin>
Digg This
Reddit This
Stumble Now!
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

不同的开发语言在性能上的两个重要差别

June 5, 2011 by · Comments Off on 不同的开发语言在性能上的两个重要差别
Filed under: c++, design, java 

不同的开发语言在性能上的重要差别,除了编译执行与解释执行的效率之外,还有两个重要的差别,一个是方法调用的性能差别,另一个是对象的创建与回收效率。

前阵子用C++(我用的VC 2010)写一个搜索本地文件的小程序,把一段代码提取为方法之后(参数使用了引用避免对象拷贝的开销),竟然发现性能有非常明显的下降,这说明C++(准确地说是VC++)的方法调用成本是相当高的。

我们在用Java处理大量的计算和IO操作时,大量的对象产生与销毁,经常会导致频繁的Full GC,Full GC的时候系统的服务几乎停滞,大大影响了系统的性能。 因此Java的内存回收效率是非常低的。 另一个方面,我们在用java时,不论方法调用的层次有多深,都几乎不会影响系统的执行性能,说明java的方法调用性能是非常高的。

Perl社区曾尝试使用纯Perl移植Lucene,然后试图通过不断的profiling和tuning来改善Perl版本Lucene的性能,最终发现由于Perl语言方法调用的成本过高,且对象的频繁创建和销毁导致性能低下而未能如愿。 参考:
http://wiki.apache.org/lucy/MinimizingObjectOverhead

Digg This
Reddit This
Stumble Now!
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

通信协议与序列化方案的纠结: Protocol Buffer, thrift or hessian?

June 2, 2011 by · 2 Comments
Filed under: java 

最早我用hessian作为java搜索服务中的通信协议和序列化方案。松耦合,部署,调用方便。这两年很多人跟我提起protocol buffer,thrift。特别是最近从不少地方的信息看到很多地方在用,也找到一些改用protocol buffer或者apache thrift的理由:

1.在趋势科技的时候,病毒清理引擎里面用的也是protocol buffer作为序列化,实际上在Trend,PB用的很广泛。

2. Jeff Dean推荐分布式系统中使用Protocol Description Language。 (理由是协议描述语言支持接口的版本演进,即可以自动忽略不认识的属性,但不是如很多中文文章翻译中所说的为了减少通信的代码量。) 参考:
http://www.parallellabs.com/2010/12/02/jeff-dean-on-google-system-architecture/
http://peopleyun.com/?p=794

3.Quora也在用Protocol Buffer。参考Quora’s Technology Examined

更为重要的是,在我们项目中.net以hessian协议调用java的过程中多次出现接口中的类版本变化,导致无法调用,且hessian并不显示有提示作用的错误信息。 调试和定位问题相当的困难和耗时。因此决定尝试 PB和thrift, 对比了两者, 发现thrift更好用,
1. thrift支持map
2. thrift提供各种语言的RPC实现,不用另外再写RPC服务器。
3. thrift官方原生版本可以自动生成各种语言的客户端,大大减少开发工作量。
参考 ”thrift与protocol buffer的比较
(注意两点,1.有评论者说thrift runtime不支持windows,实际上现在支持的 2.另一个说开始的测试结果表明Hessian比PB要快,但后来重新测试PB要快。)

但不方便的是thrift也同protocol buffer一样,需要编写定义文件, 需要生成代码, 代码中有一堆生成的方法和属性, 不如直接使用Hessian方便, 使用hessian的时候, 要开放服务的接口中压根就不需要增加任何额外的方法和属性。

使用hessian过程中,最大的问题在于前面所描述的,.net调用java hessian服务,当接口中的类版本有变化时,会调用失败。但java调用java hessian并没有这个问题。

后来到stackoverflow上查关于hessian, protocol, buffer的选择问题, stackoverflow上几个人推荐使用简洁、清晰、松耦合的hessian。最终决定仍然使用hessian,不迷信google,迷信quora,不再考虑使用thrift/java。

总结在几者之间选择的考量:
1. 如果你不需要很多语言相互调用, 希望保持清晰的java接口代码(无任何业务不相关的接口继承和方法,属性定义),减少开放工作量,推荐Hessian。

2. 如果你的系统之间传输的数据量不是很大(<2M都不算大), 推荐Hessian。 3. 如果需要支持大数据量的传输,多语言调用,极高的并发支持,推荐使用thrift/protocol buffer。 通常我们并发很难超过1000 req/s,如果超过1000 req/s,在国内互联网排名绝对前5,那么恭喜你。因此一般而言,用Hessian就够了。 Conclusion: don't bother me with Protocol Buffer or Thrift.

Digg This
Reddit This
Stumble Now!
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Running sonar in Jenkins/hudson: org.dom4j.DocumentFactory cannot be cast to org.dom4j.DocumentFactory

April 20, 2011 by · 9 Comments
Filed under: java, jenkins 

When we run sonar:sonar in Jenkins/hudson with maven,  we get the following error:

org.dom4j.DocumentException: org.dom4j.DocumentFactory cannot be cast to org.dom4j.DocumentFactory Nested exception:
org.dom4j.DocumentFactory cannot be cast to org.dom4j.DocumentFactory

I googled the message, and find it is a known problem for running jenkins with sonar:

https://issues.jenkins-ci.org/browse/JENKINS-8327

But the bug is closed without fixing.  I compared the binary class of DocumentFactory in jars in maven’s repository and the one in hudson’s WEB-INF/lib directory, there are almost identical, so I believe it should be a problem caused by classloading, object created by a different classloader could not be cast to object of the same class (will raise ClassCastException).

After a little hacking, I fixed the problem by modified 2 source files in dom4j. You can fix the problem by download my modified version of dom4j-1.6.1.jar , just download it and replace hudson’s dom4j-1.6.1-hudson-3.jar with the new one (modified java source code is included within the jar):

wget http://www.beyondlinux.com/files/dom4j-1.6.1.jar

mv /home/hudson/tomcat/webapps/hudson/WEB-INF/lib/dom4j-1.6.1-hudson-3.jar /home/hudson/dom4j-1.6.1-hudson-3.jar

mv dom4j-1.6.1.jar  /home/hudson/tomcat/webapps/hudson/WEB-INF/lib/dom4j-1.6.1-hudson-3.jar

ps, if error still occur, please replace the dom4j-1.6.1.jar in your .m2 repository with the modifed dom4j-1.6.1.jar .

 

 

 

Digg This
Reddit This
Stumble Now!
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)