Sunday, September 11, 2016

Web Service Creation and Testing - The Simplest Way

This post shows an example to create a web service that generates a response based on information received from the client. The environment is as follows:

1. EJB Container i.e. GlassFish Server

2. A stateless session bean i.e. HelloServiceBean

3. NetBeans IDE

HelloServiceBean is the endpoint implementation class. It's a stateless session bean that implements a single method: sayHello. The web service implementation class must have following requirements. 

  • The class must have annotated with javax.jws.WebService or javax.jws.WebServiceProvider annotation.
  • The implementation class may explicitly reference ans SEI through  the endpointInterfacce element of the @webService annotation but it is not mandatory. If nothoing specified, the SEI is implicitly defined for the implementation class.
  • The business methods must be public and must not be declared static or final.
  • The business methods that are exposed to web service clients must be annotated with javax.jws.WebMethod.
  • The business methods that are exposed to web service clients must have JAXB-compatible parameters and return types. See this.
  • The implementing class must not be declared final and abstract.
  • The implementing class must have a default public constructor.
  • The implementing class must be annotated with @Stateless.
  • The implementing class must not define the finalize method.
  • The implementing class may use javax.annotation.PostConstruct or javax.annotation.PreDestroy annotations on its methods for life cycle event callbacks.
The @PostConstruct method is called by the container before the implementing class begins responding to web service clients.

The @PreDestroy method is called by the container before the the endpoint class is removed from the operation.

1. Create a simple Web Application Project named HelloService and select GlassFish server and click Finish.
 



 






2. Create a class HelloServiceBean annotated with @WebService and implements the sayHello method annotated with @WebMethod. The source code of HelloServiceBean is as follows:
package com.web.helloservice;

import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebService;

/**
 *
 * @author Khan.Ashik
 */
@Stateless
@WebService
public class HelloServiceBean {

    private String message = "Hello, ";
    public HelloServiceBean() {
    }
   
    @WebMethod
    public String sayHello(String name)
    {
        return message + name + ".";
    }
}

3. Deploy the project.





▼ Test the web service without a a client

1. Open GalssFish Server administration console by opening following URL in a web browser.

 http://localhost:4848/

2.  In the left pane of the Administration Console, select the Applications node.

3. In the Applications table, click HelloService.


4. Click View Endpoint and click Test link page. If it is not present then go to following URL directly.

http://localhost:8080/HelloServiceBeanService/HelloServiceBean?Tester

5.  Under Methods, type name as parameter and click sayHello button.



6. The sayHello Method invocation page opens. Under Method Returned, The output is printed. And SOAP Request and SOAP Response XML is printed.




 If you want to learn how to create web service client and more deeply about web service, please visit my another post of Create Web Service (JAX-WS), Web Service Client and call the Web Service Using Client.
 

And that's all about this post.

Thursday, September 8, 2016

Singleton Session Bean Concurrency Control Basics with Example

This post use the same Counter project of the previous post of Singleton Session Bean Basics with Example - Counter.

Here I focus on concurrent access of different methods of a singleton session bean. There are 2 types of concurrency:

1. Container-managed concurrency

2. Bean-managed Concurrency


The javax.ejb.ConcurrencyManagement annotation is used to specify container-managed or bean-managed concurrency for the singleton. 

With @ConcurrencyManagement, a type attribute must be set to either javax.ejb.ConcurrencyManagementType.CONTAINER or javax.ejb.ConcurrencyManagementType.BEAN

If no @ConcurrencyManagement annotation is present on the singleton implementation class, the EJB container default of container-managed concurrency is used.

The following is container-managed concurrency example since no @ConcurrencyManagement annotation is present.

@Singleton
public class SingletonBean { ... }
 

The following is container-managed concurrency example with the presence of  @ConcurrencyManagement annotation.

@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@Singleton
public class
SingletonBean { ... }
 

The following is bean-managed concurrency example with the presence of  @ConcurrencyManagement annotation.


@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
@Singleton
public class
SingletonBean { ... }


1. Container-managed Concurrency

For Container-managed Singleton Session Bean, 2 annotations are used for business methods or @Timeout methods to specify the access level:

1. javax.ejb.Lock  i.e. uses: @Lock

2. javax.ejb.LockType i.e. uses: @Lock(LockType.READ) or @Lock(LockType.WRITE)

@Lock(LockType.READ) - If annotated then the method can be concurrently read or shared. This type needs to explicitly specified in method level or class level.

@Lock(LockType.WRITE) - If annotated then the method is locked to other clients while a client is calling that method. It is default lock type

The following method setState() has WRITE lock.


@Singleton
 public class
SingletonBean  

                  public void setState() 
                  {
                         //CODE
                   }

}


There are another important annotation @AccessTimeout.



@AccessTimeout:


If a method is of locking type WRITE, all client access to this method until the current client finishes its method call or access timeout occurs. This time can be defined by this annotation. When an access timeout occurs, the EJB container (i.e. application server) throws a javax.ejb.ConcurrentAccessTimeoutException.

This annotation is used to specify the time before an exception occurs.  The default time unit is MILLISECONDS. But one can set  unit one of the java.util.concurrent.TimeUnit Contants: NANOSECONDS, MICROSECONDS, MILLISECONDS or SECONDS.

The @AccessTimeout annatation can be applied to both @Lock(LockType.READ) and @Lock(LockType.WRITE) methods. And this annotation can be defined in class level or method level.


In the following example, all methods have access time 120000 milliseconds or 2 minutes except doOperation() method because it has overrides the class level (i.e. default) access timeout value to 1 minute.



@Singleton

@AccessTimeout(value=120000)
 public class
SingletonBean  

                  @Lock(LockType.WRITE)
                  public void setState() 
                  {
                         //CODE
                   }

                 @Lock(LockType.WRITE)
                  public void setName() 
                  {
                         //CODE
                   }

                 @Lock(LockType.WRITE)                  
                 @AccessTimeout(value=60, timeUnit=SECONDS)
                  public void doOperation() 
                  {
                         //CODE
                   }


}



 Example

In the next example, we'll analyze how @Lock(LockType.WRITE) method behaves when multiple client requests come. We'll use Thread.sleep(val1)  inside a @Lock(LockType.WRITE) method which has access time val2 where  
                                                             val2  <  val1

We'll find that a single client call to that method will execute. But  when multiple client call the method, then only the last one will execute and all other call will get exception due to access time is lower than method execution time.

We've the following

-  A Singleton Session bean LockBean.java with 2 methods: getState() and setState(). 

JSF2 Template Template.xhtml

- JSF2 Template client LockTest.xhtml

- Managed Bean LockTestBean.java

LockBean.java

@Singleton
@AccessTimeout(value=2000)
public class LockBean {
  
    private String state = "NO STATE";

    @Lock(LockType.READ)
    public String getState() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        return state;
    }

    @AccessTimeout(value=3000)
    public void setState(String state) {
        try {
            Thread.sleep(4000);
        } catch (InterruptedException ex) {
          
        }
        this.state = state;
    }
  
  
  
}
 
Template.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
        <link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
        <title>Counter - A singleton Session Bean Example.</title>
    </h:head>

    <h:body>

        <div id="top" class="top">
            <ui:insert name="top">Top</ui:insert>
        </div>

        <div id="content" class="center_content">
            <ui:insert name="content">Content</ui:insert>
        </div>

    </h:body>

</html>
 
  
LockTest.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html">

    <body>

        <ui:composition template="./Template.xhtml">

            <ui:define name="top">
                Lock Test in Singleton Session Bean
            </ui:define>

            <ui:define name="content">
                <h:form>
                    <h:panelGrid columns="1">
                      
                        <h:panelGroup>
                            <h:outputLabel value="State: " for="state"/>
                            <h:inputText value="#{lockTestBean.status}" id="state"/>
                            <h:commandButton value="Set State" action="#{lockTestBean.setStat()}"/>
                            <h:commandButton value="Get State" action="#{lockTestBean.getStat()}"/>
                        </h:panelGroup>
                        <h:outputText value="#{lockTestBean.message}"/>
                      
                      
                    </h:panelGrid>
                </h:form>
            </ui:define>

        </ui:composition>

    </body>
</html>


 LockTestBean.java

package com.request;

import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import test.ejb.LockBean;

/**
 *
 * @author Khan.Ashik
 */
@ManagedBean
@RequestScoped
public class LockTestBean {

    @EJB
    private LockBean lBean;
   
    private String message;
   
    private String status;
   
    /**
     * Creates a new instance of LockTestBean
     */
    public LockTestBean() {
    }
   
    public void setStat()
    {
        try
        {
            lBean.setState(status);
            message=lBean.getState();
        }
        catch(Exception e)
        {
            message = e.getMessage();
        }
       
    }
   
    public void getStat()
    {
        try
        {
           
            message=lBean.getState();
        }
        catch(Exception e)
        {
            message = e.getMessage();
        }
       
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }   
   
}

Now deploy and run the Counter application and go to

                    http://localhost:8080/Counter/faces/Locktest.xhtml 

A single client set the state. And it's OK.




 Now 2 clients wants to set the state. 1st one try to 20 and 2nd one is trying to 12. The 1st one will get exception with message Couldn't acquire a lock within 2000 MILLISECONDS and 2nd one get successful.






And this all about this post.