Friday, June 28, 2013

Notes on Weblogic JNDI, Cluster, Datasource Deployment

  1. You can bind an RMI object or a non-RMI object into a JNDI tree.
  2. When a client connects to a cluster, it is actually connecting to one of the WebLogic Servers in the cluster. Because the JNDI tree for this WebLogic Server contains the RMI stubs for all services offered by the other WebLogic Servers in the cluster in addition to its own services, the cluster appears to the client as one WebLogic Server hosting all of the cluster-wide services.
  3. When an instance of a RMI object is deployed to a single WebLogic Server, the stub is replicated across the cluster.

    Notes
    (1) Note that only the stub of the RMI object is replicated. So if the hosting server of the RMI object is down, the service given by the RMI object is also down. The RMI stubs in the other sever's JNDI tree are updated to reflect the server failure.
    (2) When you deploy a data source to a cluster, WebLogic Server creates an instance of the data source on each server in the cluster. So in this case, each server has an actual instance instead of a stub. So even if one server goes down, the data source in other servers can still work.

  4. When a customer object ( a non-RMI object) is bound into a JNDI tree in a cluster, the object is replicated across all the servers in the cluster. However, if the host server goes down, the customer object is removed from teh cluster's JNDI tree.
    To create a binding that is not replicated across WebLogic Servers in a cluster, you must specify the REPLICATE_BINDING property to "false" when creating the context that binds the customer object.
  5. A client can use the ClusterAddress to get the service. This address may be either a DNS host name that maps to multiple IP addresses or a comma separated list of single address host names or IP addresses. An alternative method of specifying the initial point of contact with the WebLogic Cluster is to supply a comma-delimited list of DNS Server names or IP addresses. Examples:
       Hashtable ht = new Hashtable();
       ht.put(Context.PROVIDER_URL, "t3://acme1,acme2,acme3:7001");
    or
    ht.put(Context.PROVIDER_URL, "t3://node1:7001,node2:7002,node3:7003");

References

  1. Programming WebLogic JNDI(http://docs.oracle.com/cd/E15051_01/wls/docs103/jndi/jndi.html)
  2. Deploying Data Sources on Servers and Clusters (http://docs.oracle.com/cd/E23943_01/web.1111/e13737/ds_deploy.htm)

Wednesday, May 1, 2013

Notes on how to configure key files for SSH connection

Login onto Linux. When you first SSH to another server with the following command:
ssh someuser@remoteServer
You will get the prompt like the following:
The authenticity of host 'remoteServer (XX.XX.XX.XX)' can't be established.
RSA key fingerprint is d9:5e:8d:9d:59:12:39:e9:ff:59:57:07:92:ef:52:b2.
Are you sure you want to continue connecting (yes/no)? 
Type yes. Now you will be prompted to enter the password for the user "someuser" to login to remoteServer.
Just type the password. And now you should be successfully connected to remoteServer.

When you ssh to a remote server, your ssh client records the hostname, IP address and public key of the remote server in a flat file called "known_hosts". As such, the .ssh directory on your local server will now have the known_hosts file that contains an entry for remoteServer. The entry looks like the following:

remoteServer,XX.XX.XX.XX ssh-rsa AAAAB3NzaC1yc.....
In the above entry, the string after ssh-rsa is the public key of remoteServer. Where is this public key located on remoteServer? There can be different user accounts on remoteServer. And each account can create its own keys. But when you ssh to remoteServer, you will get the same public key. This key is actually at the location /etc/ssh/ssh_host_rsa_key.pub.

Now on your local server, execute the following command to generate the public/private keys:

ssh-kygen -t rsa
It will prompt you to enter the file in which to save the generated key and also prompt you to enter passphrase.
Just take the default and return to use the empty passphrase. This will create the private key id_rsa and the public key id_rsa.pub in the .ssh directory.

Logon to remoteServer. In the home directory for the user someuser on remoteServer, there is the .ssh folder. If this folder has a file authorized_keys, then append the content of the public key file id_rsa.pub that you generated on your local server to the end of authorized_keys. If authorized_keys file does not exist, then create it and copy the content of id_rsa.pub to this file.

Now if you do the following on your local server:

ssh someuser@remoteServer
You should be able to logon to remoteServer directly without the need to type password.

Friday, February 1, 2013

Fractals

I made a program using java Swing that can easily draw fractals that are generated as the attractors of the math IFS ( Iterated Function Systems). The following is a sample picture. It is a tile of a self-affine tiling of the plane R^2. The IFS consists of 3 functions {f1(x),f2(x), f3(x)}. The 3 functions are defined as follows:
f1(x) = (B^2)^(-1)(x)
f2(x) = (B*w*B)^(-1)(x + B*h)
f3(x) = B^(-1)(x + d)
where B is the matrix {{1, -1},{1,1}}, w is the matrix {{0,-1},{1,0}}, h = {0,1}, and d={1,0}.

Note that the picture consists of 3 pieces that are similar to each other. The 3 pieces do not overlap. They only touch others at the borders. Though the boundary of the whole picture is very complex, we can use similar copies of this shape of different sizes to tile the whole plane without overlapping! And we only need finitely many different sizes of this shape for the tiling.

Friday, January 25, 2013

JAXWS proxy

JDK 6 has the wsimport tool that can be used to generate java classes based on the given wsdl file. Then the webservice client can use those classes to call the web service. The following is the example code:
public void testMyService(){
  MyService service = new MyService();
  port = service.getMyPort();
  port.doSomething();
}
In the above, the class MyService is generated by wsimport. It has many annotations related to web service. It is a subclass of javax.xml.ws.Service. MyService is actually a proxy. The following is from the javadoc of the class Service:

Service objects provide the client view of a Web service.

Service acts as a factory of the following:

  • Proxies for a target service endpoint.
  • Instances of {@link javax.xml.ws.Dispatch} for dynamic message-oriented invocation of a remote operation.
Now the questions are these. How is the proxy actually created in the runtime? How are those annotations used? The following is the stack of the method calls at the point when the proxy is created:
 Thread [Main Thread] (Suspended (breakpoint at line 574 in Proxy)) 
  Proxy.newProxyInstance(ClassLoader, Class<?>[], InvocationHandler) line: 574 
  AnnotationParser.annotationForMap(Class, Map) line: 239 
  AnnotationParser.parseAnnotation(ByteBuffer, ConstantPool, Class, boolean) line: 229 
  AnnotationParser.parseAnnotations2(byte[], ConstantPool, Class) line: 69 
  AnnotationParser.parseAnnotations(byte[], ConstantPool, Class) line: 52 
  Class<T>.initAnnotationsIfNecessary() line: 3070 
  Class<T>.getAnnotation(Class<A>) line: 3029 
  AnnotationType.<init>(Class<?>) line: 113 
  AnnotationType.getInstance(Class) line: 66 
  AnnotationParser.parseAnnotation(ByteBuffer, ConstantPool, Class, boolean) line: 202 
  AnnotationParser.parseAnnotations2(byte[], ConstantPool, Class) line: 69 
  AnnotationParser.parseAnnotations(byte[], ConstantPool, Class) line: 52 
  Class<T>.initAnnotationsIfNecessary() line: 3070 
  Class<T>.getAnnotation(Class<A>) line: 3029 
  RuntimeInlineAnnotationReader.getClassAnnotation(Class<A>, Class, Locatable) line: 106 
  RuntimeInlineAnnotationReader.getClassAnnotation(Class, Object, Locatable) line: 57 
  RuntimeModelBuilder(ModelBuilder<T,C,F,M>).getTypeInfo(Ref<T,C>) line: 330 
  JAXBContextImpl.getTypeInfoSet() line: 460 
  JAXBContextImpl.<init>(JAXBContextImpl$JAXBContextBuilder) line: 298 
  JAXBContextImpl.<init>(JAXBContextImpl$JAXBContextBuilder, JAXBContextImpl$1) line: 141 
  JAXBContextImpl$JAXBContextBuilder.build() line: 1163 
  ContextFactory.createContext(Class[], Map) line: 145 
  NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
  NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
  DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
  Method.invoke(Object, Object...) line: 597 
  ContextFinder.newInstance(Class[], Map, String) line: 202 
  ContextFinder.find(Class[], Map) line: 363 
  JAXBContext.newInstance(Class[], Map) line: 574 
  JAXBContext.newInstance(Class...) line: 522 
  ProviderImpl$2.run() line: 209 
  ProviderImpl$2.run() line: 206 
  ProviderImpl.getEPRJaxbContext() line: 206 [local variables unavailable] 
  ProviderImpl.() line: 77 [local variables unavailable] 
  NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method] 
  NativeConstructorAccessorImpl.newInstance(Object[]) line: 39 
  DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 27 
  Constructor<T>.newInstance(Object...) line: 513 
  Class<T>.newInstance0() line: 355 [local variables unavailable] 
  Class<T>.newInstance() line: 308 [local variables unavailable] 
  FactoryFinder.newInstance(String, ClassLoader) line: 31 
  FactoryFinder.find(String, String) line: 128 
  Provider.provider() line: 83 [local variables unavailable] 
  MyService(Service).<init>(URL, QName) line: 56 
  MyService.<init>() line: 46 
  SimpleClient.testMyService() line: 86 
  SimpleClient.main(String[]) line: 108 
This stack gives some clue about how the proxy is created.
  1. MyService is the class generated by wsimport.
  2. The following call to the constructor
         service = new MyService()
    
    calls the constructor of the super class Service. And the following code is executed:
       protected Service(java.net.URL wsdlDocumentLocation, QName serviceName) {
            delegate = Provider.provider().createServiceDelegate(wsdlDocumentLocation,
                    serviceName,
                    this.getClass());
        }
        
    This corresponds to
            MyService(Service).<init>(URL, QName) line: 56 
         
    in the stack.
  3. Now you can see that the Provider picks up the duty and will do all the heavy work. It uses the input parameters wsdlDocumentLocation, serviceName and Class to create the delegate object. The Provider is javax.xml.ws.spi.Provider. My guess is that the Class object this.getClass() contains all the annotation information of the class MyService. The stack shows the process uses the following classes:
    (1)RuntimeInlineAnnotationReader (package: com.sun.xml.bind.v2.model.annotation)
    (2)AnnotationParser (package: sun.reflect.annotation)

  4. These classes process the annotations.

Monday, January 21, 2013

How to set handlers on the JAX-WS client side

In webservice, handlers can be used for logging messages, implmenting security,etc. For a JAX-WS client, there are several ways to set handlers.

Use xml binding

The handlers can be set by binding a handler XML file.
import javax.xml.ws.Service;

@WebServiceClient(name = "MyService", targetNamespace = "...", wsdlLocation = "...")
@HandlerChain(file = "MyService_handler.xml")
public class MyService extends Service{
...
}
MyService_handler.xml:
<?xml version="1.0" encoding="UTF-8"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee">
  <javaee:handler-chain>
    <javaee:handler>
      <javaee:handler-class>com.my.SOAPHandler1</javaee:handler-class>
    </javaee:handler>
    <javaee:handler>
      <javaee:handler-class>com.my.SOAPHandler2</javaee:handler-class>
    </javaee:handler>
  
  </javaee:handler-chain>
</javaee:handler-chains>

Set handlers programmatically

The handlers can also be set programmatically. You can use BindingProvider to set the handlers.
import javax.xml.ws.BindingProvider;

 MyService service = new MyService(wsdlLoc, qName);
 port = service.getXXX();
 BindingProvider bp = (BindingProvider) port;
 Binding binding = bp.getBinding();
 List<Handler> handlerList = binding.getHandlerChain();
 MySOAPHandler myHandler = new MySOAPHandler();
 handlerList.add(myHandler );
 bp.getBinding().setHandlerChain(handlerList);

 port.callXYZ(...);
        
You can also use HandlerResolver to set handlers.

    import javax.xml.ws.handler.Handler;
    import javax.xml.ws.handler.HandlerResolver;
    import javax.xml.ws.handler.PortInfo;

        MyService service = new MyService(wsdlLoc, qName);
       
        service.setHandlerResolver(new HandlerResolver() {
        @Override public List getHandlerChain(PortInfo portInfo) { 
         List<Handler> handlerChain = new ArrayList<Handler>(); 
         handlerChain.add(new MySOAPHandler()); 
         return handlerChain; 
       } 
     });
     
      port = service.getXXX();
      port.callXYZ(...);
But be careful that the code "port = service.getXXX()" must be put after service.setHandlerResolver(...). If it is put before the call setHandlerResolver(...), the code won't work.

References

  1. http://www.javaworld.com/javaworld/jw-02-2007/jw-02-handler.html
  2. http://jax-ws.java.net/nonav/2.2.7/docs/index.html

Monday, September 17, 2012

Blog Three Year Anniversary

I just checked the date. Today is September 17, 2012. This blog site was created on September 12, 2009. So I just passed the three year anniversary by 5 days. Time flies ! The weather is good. Last week it was around 80F with little rain in Pittsburgh. Leaves have turned yellow or red a bit. This week it is getting a little cool. The temperature is around 70F.

Thursday, July 26, 2012

Various Ways for Navigation in JSF 2(draft)

The example is taken from the Icefaces 3 turorial http://wiki.icesoft.org/display/ICE/Getting+Started+with+ICEfaces+3 The file job-applicant.xhtml uses several navigation mechanisms.
  • Use the following:
     <h: button outcome="xyz" .../>
    The web will go directly xyz.xhtml. The URL in the browser is changed to something like ***/xyz.jsf
  • Use the following:
    <h:commandButton action="xyz" ... />
    Go to faces-config.xml to look for the <from-outcome> match for this page. The value in the <to-view-id> tag will be used and the the URL will be changed accordingly.
  • Use the following:
    <h:commandButton action="#{bean.method}" ... />
    Invoke the method of the bean. The return value is a string.
    1. The returned result is the following "abc?faces-redirect=true". In this case, the web will go to abc.xhtml. The URL is changed.
    2. The returned result is the following "abc". In this case, the web will show the content of abc.xhtml. But the URL will not change. So if the current page is xyz.xhtml, the new URL will still be xyz.xhtml instead of abc.xhtml.
    Note that this case of using bean method for the 'action' attribute in h:commandButton is syntactically the same as the case of using string literal for the 'action' attribute in h:commandButton. So maybe the navigation rule is the same. The navigation will first look for the match in faces-config.xml. If a match is not found, then it will just use the value of the 'action' attribute as the page name. It will either redirect to it or forward to it depending on the redirect flag.
  • <h:commandButton listener="#{bean.method}" ... />
    or
    <h:commandButton actionListener="#{bean.method}" ... />
    In these cases, the method returns void. So by default, the page submits to itself. The URL does not change.