Tuesday, September 18, 2012

clear statement cache in weblogic


This case confused me for hours today. I have a web service app hosted by weblogic v10.3.

A tester used an appId which is a part of input to call a web service. The server need to query database based on the appId passing from web service client. So it is ok system returned null because there was no data about the appId in database.
I added the appId in database, and tried to call again. It was suprised that system still returned null, while there was something returned if I tested it via junit class.

The only possibility is that server, whatever weblogic server or database server, returns historical data from cache.By default, weblogic set statement cache type as LRU and cache size as 10, refer to http://docs.oracle.com/cd/E12839_01/web.1111/e13737/jdbc_datasources.htm#JDBCA171 and oracle jdbc implemention caches the test result,refer to http://docs.oracle.com/cd/B10501_01/java.920/a96654/stmtcach.htm, so that is why I got unexpected result before clearing the statement cache in weblogic. (how to clear statement cache, refer to http://docs.oracle.com/cd/E16764_01/apirefs.1111/e13952/taskhelp/jdbc/jdbc_datasources/ClearStatementCache.html)

Thursday, August 2, 2012

Tomcat Cluster


apache v2.2.22
tomcat v6.0.32

instance1: c:\cluster1
instance2: c:\cluster2

1) There are two options to configure communication between app server and web server, mod_jk and mod_proxy

A pros/cons comparison for those modules from http://blog.jboss.org/ is as follows,

mod_proxy:

* Pros:
      o No need for a separate module compilation and maintenance. mod_proxy,
        mod_proxy_http, mod_proxy_ajp and mod_proxy_balancer comes as part of
        standard Apache 2.2+ distribution
      o Ability to use http https or AJP protocols, even within the same
        balancer.
* Cons:
      o mod_proxy_ajp does not support large 8K+ packet sizes.
      o Basic load balancer
      o Does not support Domain model clustering

mod_jk:

* Pros:
      o Advanced load balancer
      o Advanced node failure detection
      o Support for large AJP packet sizes
* Cons:
      o Need to build and maintain a separate module


1.1) jk connector

a) download mod_jk.so from http://tomcat.apache.org/download-connectors.cgi and put it to modlules folder in apache.

b) create two new files mod_jk.conf and workers.properties and put them to conf folder in apache.

-- content of mod_jk.conf
LoadModule jk_module modules/mod_jk.so      # load mod_jk.so  
JkWorkersFile conf/workers.properties       # load workers file  
JkLogFile logs/mod_jk.log
JkLogLevel info
JkMount  /*  loadbalancer                     # forward all incoming requests to loadbalancer    
#JKMount /*.jsp loadbalancer                  # forward requests from jsp file to loadbalancer
HostnameLookups Off

-- content of workers.properties
worker.list = loadbalancer,cluster1,cluster2   # a list of servers in cluster
#========cluster1========
worker.cluster1.port=8889                    
worker.cluster1.host=localhost                
worker.cluster1.type=ajp13
worker.cluster1.lbfactor = 1                  
#========cluster2========
worker.cluster2.port=8899
worker.cluster2.host=localhost
worker.cluster2.type=ajp13
# The higher the value of the lbfactor for Tomcat instance, the more work the server will do, and vice versa
worker.cluster2.lbfactor =1                
#========loadbalancer======
worker.loadbalancer.type=lb                           # load balancer
worker.loadbalancer.balanced_workers=cluster1,cluster2
# keep requests belonging to the same session (which means the same user) forwarded to the same worker
worker.loadbalancer.sticky_session=false            

c) add one more statement at the end of file httpd.conf

include conf/mod_jk.conf  # load mod_jk.conf

2) edit server.xml in instance cluster1

2.1) change listen port for shutdown <Server port="8005" shutdown="SHUTDOWN"> to <Server port="8006" shutdown="SHUTDOWN">
2.2) change listen port for connector
   <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL HTTP/1.1 Connector on port 8080
    -->
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
to
<Connector port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
2.3) change port for AJP
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
to
<Connector port="8889" protocol="AJP/1.3" redirectPort="8443" />
2.4) uncomment the engine element and specify the value for jvmRoute
<!-- You should set jvmRoute to support load-balancing via AJP ie :-->
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="cluster1">        
 
2.5) uncomment this element to enable all-to-all session replication using the DeltaManager to replicate session deltas which replica session to all the other nodes in the cluster.

the other option is to replicate session to backup node only, see http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

3) edit server.xml in instance cluster1

3.1)  <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
to
<Connector port="8899" protocol="AJP/1.3" redirectPort="8443" />
3.2) uncomment the engine element and specify the value for jvmRoute
 <Engine name="Catalina" defaultHost="localhost" jvmRoute="cluster2">        
3.3) uncomment this element
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

4) create a new web application, the element <distributable/> must be configured in its web.xml

5) add a index.jsp file to test.

<%@ page contentType="text/html; charset=utf-8" %>
<%@ page import="java.util.*" %>

<html><head><title>Cluster App Test</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%

  out.println("<br> ID " + session.getId()+"<br>");

  String dataName = request.getParameter("dataName");

  if (dataName != null && dataName.length() > 0) {

     String dataValue = request.getParameter("dataValue");

     session.setAttribute(dataName, dataValue);

  }

  out.println("<b>Session List</b><br>");

  System.out.println("============================");

  Enumeration e = session.getAttributeNames();

  while (e.hasMoreElements()) {

     String name = (String)e.nextElement();

     String value = session.getAttribute(name).toString();

     out.println( name + " = " + value+"<br>");

         System.out.println( name + " = " + value);
   }

%>

<form action="index.jsp" method="POST">
    Name:<input type=text size=20 name="dataName"><br/>
    Value:<input type=text size=20 name="dataValue"><br/>
    <input type=submit>
</form>
</body>
</html>

6) test

working fine with this scenario described in http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html#How_it_Works

if set sticky_session to true
worker.loadbalancer.sticky_session=true

The session still can be replicated to other workers. so need to add this configure to force sticky session in worker.properties

worker.loadbalancer.sticky_session_force=1

MySQL Index Tips


  • 索引不要包含有NULL值的列

只要列中包含有NULL值都将不会被包含在MySQL索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

  • 使用短索引

对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

  • 索引列排序

MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引

  • like语句操作

一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用MySQL索引而like “aaa%”可以使用索引。

  • 不要在列上进行运算

select * from users where YEAR(adddate)<2007;  

将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成

select * from users where adddate<‘2007-01-01’;  

不使用NOT IN和<>操作


转载自: http://club.topsage.com/thread-2205632-1-2.html

Tuesday, May 29, 2012

Java program to encrypt password for LDAP entry


In the LDAP server, let's say oracle identity directory (OID) or OpenLDAP, we are allowed to configure the encoding algorithm, SHA,MD5,SHAA,etc, to hash the user password.

if the password is 'abcd1234', the password in ldap will be stored as '{SHA}fOA1nxKFfyqQx95GX0CpXwHLXak=' in userPassword attribute.

This is the java program to encrypt the password with SHA to simulate how LDAP to encrypt user password.

package test.ldap.sha;

import java.security.MessageDigest;

import sun.misc.BASE64Encoder;

public class PasswordEncryptor {

public static void main(String[] args) throws Exception {
String pwdPlainText = "abcd1234";

MessageDigest md = MessageDigest.getInstance("SHA");
md.update(pwdPlainText.getBytes());
byte raw[] = md.digest();

BASE64Encoder base64 = new BASE64Encoder();
String result = "{SHA}" + base64.encode(raw);
System.out.println("userpassword in LDAP:" + result);

String pwdGeneratedByLdap = "{SHA}fOA1nxKFfyqQx95GX0CpXwHLXak=";
System.out.println(pwdGeneratedByLdap.equals(result));

}
}

This is output:
userpassword in LDAP:{SHA}fOA1nxKFfyqQx95GX0CpXwHLXak=
true

Monday, May 14, 2012

Design Pattern Study Notes 5 - Builder


























1) interface to define build methods.
============== Builder.java ================

package test.pattern.builder;
/**
 *  interface
 *
 */
public interface Builder {
public abstract void doPart1();
public abstract void doPart2(String para);
public abstract void doPart3(int para);
public abstract Product getProduct();
}

2) to create product object
============== Director.java =============
package test.pattern.builder;

public class Director {

private Builder builder;

public Director(Builder builder) {
this.builder = builder;
}

public Product construct(String para, int para2) {
builder.doPart1();
builder.doPart2(para);
builder.doPart3(para2);
Product product = builder.getProduct();
return product;
}
}

3) product class
============== Product.java =============
package test.pattern.builder;

public class Product {

private String component1;
private int component2;
        // getter and setter methods
}

4) concrete builder: 
a) implement the methods defined in above interface to build the product step by step
b) return the product instance

============== ConcreteBuilder1.java ==================
package test.pattern.builder;

public class ConcreteBuilder1 implements Builder {
Product prod = new Product();

public void doPart1() {
System.out.println("execute builder1:part1");
}

public void doPart2(String para) {
System.out.println("execute builder1:part2:" + para);
prod.setComponent1(para);
}

public void doPart3(int para) {
System.out.println("execute builder1:part3:" + para);
prod.setComponent2(para);
}

public Product getProduct() {
return prod;
}

}

=============== ConcreteBuilder2.java ==============
package test.pattern.builder;

public class ConcreteBuilder2 implements Builder {
Product prod = new Product();

public void doPart1() {
System.out.println("execute builder2:part1");
}

public void doPart2(String para) {
System.out.println("execute builder2:part2:" + para);
prod.setComponent1(para);
}

public void doPart3(int para) {
System.out.println("execute builder2:part3:" + para);
prod.setComponent2(para);
}

public Product getProduct() {
return prod;
}
}

5) test class
============== Client.java =================
package test.pattern.builder;

public class Client {

public static void main(String[] args) {
Director director = new Director(new ConcreteBuilder1());
Product prod = director.construct("do something", 4);
System.out.println("got: " + prod.getComponent1());
System.out.println("got: " + prod.getComponent2());

director = new Director(new ConcreteBuilder2());
prod = director.construct("do something else", 5);
System.out.println("got: " + prod.getComponent1());
System.out.println("got: " + prod.getComponent2());
}

}

This is the output:
execute builder1:part1
execute builder1:part2:do something
execute builder1:part3:4
got: do something
got: 4
execute builder2:part1
execute builder2:part2:do something else
execute builder2:part3:5
got: do something else
got: 5


Thursday, May 10, 2012

Design Pattern Study Notes 4 - Singleton













Problem:
only one instance in the system.

Solution:
Singleton pattern

1) singleton class
===================== Singleton.java ====================
package test.pattern.singleton;

public class Singleton {

private static Singleton instance = null;

/*
* the constructor must be private
*/
private Singleton() {
System.out.println("private constructor");
}

/*
* just in case running in multi-thread env,need to add synchronized
*/
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}

return instance;
}
}

2) test class
==================== Client.java ====================
package test.pattern.singleton;

public class Client {

public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1==s2);
}
}

This is the output:
private constructor
true


Design Pattern Study Notes 3 - Template Method




















Problem:
need to define the process or logic on the top class, and implement the detail logic at lower classes

Solution:
Template method pattern

1) top abstract class
=============== Template.java ================

package test.pattern.template;

public abstract class Template {

public void process() {
beforeOperation();
operation();
afterOperation();
}

private void beforeOperation() {
System.out.println("before action.");
}

private void afterOperation() {
System.out.println("after action.");
}

public abstract void operation();
}

2) sub class to implement the abstract method
================= TemplateImpl.java ==============

package test.pattern.template;

public class TemplateImpl extends Template {

public void operation() {
System.out.println("do something.");

}
}

3) the other sub class to implement the abstract method

================== TemplateImpl2.java =================
package test.pattern.template;

public class TemplateImpl2 extends Template {

public void operation() {
System.out.println("do something else.");
}
}


4) test class
=================== Client.java ==================
package test.pattern.template;

public class Client {

public static void main(String[] args) {
Template t1 = new TemplateImpl();
t1.process();

Template t2 = new TemplateImpl2();
t2.process();

}

}

This is the output:

before action.
do something.
after action.
before action.
do something else.
after action.



Design Pattern Study Notes 2 - Adapter














Problem:
If want to reuse the existing class, but its interface does not meet the new requirement.

Solution:
Adapter pattern.

1) This is new interface we want to implement.
======================== Target.java ====================

package test.pattern.adapter;

public interface Target {

public void methodA();
public void methodB();
}

2) This is the existing class we have.
======================= Adaptee.java ================

package test.pattern.adapter;

public class Adaptee {

public void methodA() {
System.out.println("it is method A.");
}
}

3) This is an adapter class to implement above new interface Target.java
=================== Adapter.java =====================
package test.pattern.adapter;

public class Adapter extends Adaptee implements Target {

public void methodB() {
System.out.println("it is method B.");
}

}

4) This is another adapter to implement above new interface Target.java
=================== Adapter2.java ====================
package test.pattern.adapter;

public class Adapter2 implements Target {

private Adaptee adaptee;

public Adapter2(Adaptee adaptee) {
this.adaptee = adaptee;
}

public void methodA() {
this.adaptee.methodA();
}

public void methodB() {
System.out.println("this is method B.");
}

}

5) test class
============== Client.java ======================
package test.pattern.adapter;

public class Client {

public static void main(String[] args) {
Target adapter = new Adapter();
adapter.methodA();
adapter.methodB();

Adaptee adaptee = new Adaptee();
Target adapter2 = new Adapter2(adaptee);
adapter2.methodA();
adapter2.methodB();
}

}

This is output:
it is method A.
it is method B.
it is method A.
this is method B.



Wednesday, May 9, 2012

Design Pattern Study Notes 1 - Iterator


Problem:
A team has one or multiple members, now print the member information one by one.

Solution:
iterator pattern.

1) define an iterator interface.
====================== MyIterator.java ==================
package test.pattern.iterator;

/**
 *  This is the customized iterator interface.
 *
 */
public interface MyIterator {
public boolean hasNext();

public Object next();
}

2) define aggregate interface

====================== Aggregate.java ==================

package test.pattern.iterator;

public interface Aggregate {
MyIterator iterator();
}

3) member class to encapsulate member's information
====================== Member.java =====================
package test.pattern.iterator;

public class Member {
private String name;
private int age;

        // getter and setter methods
}

4) team class to implement Aggregate class
==================== Team.java =======================
package test.pattern.iterator;

public class Team implements Aggregate {

private Member[] members;
private int last;

public Team(int maxSize) {
members = new Member[maxSize];
this.last = 0;
}
public void addMember(Member member){
this.members[last]=member;
last++;
}

public int getLength() {
return members.length;
}

public Member getMemberAt(int index) {
return members[index];
}

public MyIterator iterator() {
return new TeamIterator(this);
}

}

5) TeamIterator class to implement MyIterator interface
=================== TeamIterator.java ================

package test.pattern.iterator;

public class TeamIterator implements MyIterator {

private Team team;
private int index;

public TeamIterator(Team team) {
this.team = team;
this.index = 0;
}

public boolean hasNext() {

if (index >= 0 && index < team.getLength())
return true;
return false;
}

public Object next() {
Member member = team.getMemberAt(index);
index++;
return member;
}

}

6) test class
==================== Client.java ===================
package test.pattern.iterator;

public class Client {

public static void main(String[] args) {
Team team = new Team(5);
team.addMember(new Member("member A", 10));
team.addMember(new Member("member B", 11));
team.addMember(new Member("member C", 12));
team.addMember(new Member("member D", 13));
team.addMember(new Member("member E", 15));

MyIterator it = team.iterator();
while (it.hasNext()) {
Member mem = (Member) it.next();
System.out.println(mem.getName() + "'s age is " + mem.getAge());
}

}

}

This is the output:
member A's age is 10
member B's age is 11
member C's age is 12
member D's age is 13
member E's age is 15

------------
After jdk1.5,  for-loop is another solution.