My name is Gurkan Erdogdu and I am the CTO of the MechSoft Mechanical and Software Solutions. I have been active in the Java and Java EE platform more than 10 years. Strong supporter for the Free and Open Source Software, and actively participating within the Open Source based foundations like, Apache Software Foundation, JBoss, and recently Open Web Foundation. I am the member of the Apache Software Foundation and Open Web Foundation. Writing blog at gurkanerdogdu@blogspot.com. Gurkan has posted 24 posts at DZone. View Full User Profile

Getting Started With Defne Web Framework and Apache OpenWebBeans

07.15.2010
| 4465 views |
  • submit to reddit

Defne is a service oriented web application framework. The main motivation behind Defne is ease of use. Defne allows developers to concentrate on their business logic while it provides all other application requirements such as transaction and security. With Defne, you can implement powerful enterprise web applications on time and with a service oriented fashion.

Required Runtime
Defne requires Java runtime less than or equal to 1.5. Moreover, it requires OpenWebBeans and JPA runtimes for dependency injection and database operations, respectively.

SIwpas simple web application server, http://code.google.com/p/siwpas , provides necessary runtimes to use Defne framework.

Writing a First Service
In this getting started guide, we will implement a registery form using Defne. We will use JSF 2.0 to implement our web application's GUI. Complete source code of this web application can be downloaded from svn.

Defne Concepts

  • Defne Service: POJO class annotated with @Service
  • Defne Operation: POJO class static method annotated with @Operation and obeys the following method signature, (serviceName is any application Java method name)

    public static Message <serviceName>(Message input) throws DefneException
  • Defne Transaction: Transactions are provided while calling service operation. TransactionPolicy enum contains the following entries:

          NO_TRANSACTION, Do not use any JPA transaction
          WITH_TRANSACTION, Run within JPA transaction
          NEW_TRANSACTION,  Not supported currently without using EJB executors(defne-ejb).

  • Defne Security: Defne provides annotated based security configuration. It provides @Roles annotation to configure security roles on service operations. Defne framework provides Service Provider Interface(SPI) org.defne.security.spi.IPrincipal for implementing by the Defne runtimes. It allows Defne to get currently logined user roles from an application server.

Currently only SIwpas based implementation is provided, org.defne.security.impl.SiwpasProvidedPrincipal. To use this security implementation in our applications, we have to add the following entry to web application beans.xml file.(This is the same for the Apache Tomcat 7)

<beans>
<alternatives>
<class>org.defne.security.impl.SiwpasProvidedPrincipal</class>
</alternatives>
</beans>


Ok, let's start to write some service code.

Request Flow

When a service request is issued from a web browser, the following actions are occured on the server side,

OpenWebBeans Managed Bean calls OwbServiceExecutor Proxy calls OwbServiceExecutor calls Actual Service

OwbServiceExecutor Proxy and OwbServiceExecutor are provided by the Defne Framework. Therefore, your responsibility is to implement Managed Bean and Service.

OpenWebBeans managed bean is a managed bean that injects OwbServiceExecutor Proxy instance using @Inject @PojoExecutorProxy IServiceExecutorProxy pojoExecutor. Proxy handles all of the transaction, security, JPA stuff etc. If everthing is successful on proxy side, proxy calls service executor that calls the actual service. Funny haaa!!!

JPA Entity Class

@Entity
public class Person
{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;

@Column
private String name;

@Column
private String surname;

public int getId()
{
return id;
}

public void setId(int id)
{
this.id = id;
}

public String getName()
{
return name;
}

public void setName(String name)
{
this.name = name;
}

public String getSurname()
{
return surname;
}

public void setSurname(String surname)
{
this.surname = surname;
}
}




OpenWebBeans Managed Bean

@Named
@RequestScoped
public class RegisterBean {

//Injection of service executor proxy
private @Inject @PojoExecutorProxy IServiceExecutorProxy pojoExecutor;

private String message;

private String name;

private String surname;

public RegisterBean()
{

}

public String register()
{
//Creating a message
Message input = MessageFactory.newMessage(IRegisterService.SERVICE_NAME,IRegisterService.RegisterOperation.OPERATION_NAME);

//Calling with JPA transaction
input.putMessageParameter(IMessageConstants.SERVICE_CALLER_TRANSACTION_POLICY, TransactionPolicy.WITH_TRANSACTION);

//Adding service parameters
input.putMessageParameter(IRegisterService.RegisterOperation.INPUT.NAME, this.name);
input.putMessageParameter(IRegisterService.RegisterOperation.INPUT.SURNAME, this.surname);

//Execute servcie
input = this.pojoExecutor.execute(input);

//Any message
this.message = input.getMessageParameter(String.class, IRegisterService.RegisterOperation.OUTPUT.MESSAGE);

return null;

}

public String getMessage()
{
return message;
}

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

public String getName()
{
return name;
}

public void setName(String name)
{
this.name = name;
}

public String getSurname()
{
return surname;
}

public void setSurname(String surname)
{
this.surname = surname;
}
}


Our Service Code

Service is composed of 2 components, service descriptor interface and service class,

Service descriptor interface,

public interface IRegisterService
{
String SERVICE_NAME = "RegisterService";

public interface RegisterOperation{
String OPERATION_NAME = "register";

public interface INPUT{
String NAME = "NAME";
String SURNAME = "SURNAME";
}

public interface OUTPUT{
String MESSAGE = "MESSAGE";
}
}
}


Service code,

@Service
public class RegisterService
{
@Operation
public static Message register(Message inBag) throws DefneException
{
String name = inBag.getMessageParameter(String.class, IRegisterService.RegisterOperation.INPUT.NAME);
String surname = inBag.getMessageParameter(String.class, IRegisterService.RegisterOperation.INPUT.SURNAME);

EntityManager entityManager = EntityManagerUtil.getEntityManagerFromBag(inBag);

Person person = new Person();
person.setName(name);
person.setSurname(surname);

entityManager.persist(person);

inBag.putMessageParameter(IRegisterService.RegisterOperation.OUTPUT.MESSAGE, "Registered user, " + name + surname );

return inBag;
}
}


Writing our JSF Page

Register page, register.xhtml

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Defne :: Owb Register Page</title>
</h:head>
<h:body>

<h:form id="form">

<div>
<h:outputText value="Your Name : " />
<br/>
<h:inputText value="#{registerBean.name}"></h:inputText>
<br/>
<h:outputText value="Your SurName : " />
<br/>
<h:inputText value="#{registerBean.surname}"></h:inputText>

<br/>
<h:commandButton action="#{registerBean.register}" value="Register" />

</div>

<div>
<h:outputText value="#{registerBean.message}"></h:outputText>
</div>

</h:form>

</h:body>
</html>


Update Configuration Files

WEB-INF/beans.xml,

<beans>
<alternatives>
<class>org.defne.security.impl.SiwpasProvidedPrincipal</class>
</alternatives>
</beans>


WEB-INF/web.xml

<web-app id="WebApp_ID" version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<listener>
<listener-class>org.defne.service.scanner.ScannerListener</listener-class>
</listener>

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>


<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>

<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>

</web-app>


Deploy it into the SIwpas

That is it, deploy it int the container. If you wish to use core Apache Tomcat, you have to add all of Defne dependencies to Tomtcat lib folder or bundle with application WEB-INF/lib.

Hit browser URL

http://localhost:8080/owb-register/register.jsf

 

Calling Services From Pure AJAX Client


Defne also provides hooking points for calling services from JavaScript. Defne provides JSON Servlet for executing the AJAX requests that are targeted for server side services.

For example, below is the jQuery AJAX request that calls Defne service residing on the server side;

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

function postjson(){
$.ajax({type:"POST",url:"/json-example/DefneJson",data:"{'adaptorClass':'org.samples.jsonexample.HelloAdaptor','service':'HelloService','method':'sayHello','args':{'NAME':'Gurkan','SALARY':'1000'}}",
dataType:"json"});
}

$(document).ready(function() {
$("#myb").click(function(event){
postjson();
});
});


In JSON case, developer is required to implement IJsonAdaptor interface to change Map<String,String> to Message and vice versa. For example ,

public class HelloAdaptor implements IJsonAdaptor
{

@Override
public Map<String, String> fromOutputMessage(Message message)
{
Map<String, String> out = new HashMap<String, String>();
out.put("MESSAGE", message.getMessageParameter(String.class, "MESSAGE"));

return out;
}

@Override
public Message toInputMessage(String service, String method, Map<String, String> args)
{
Message message = MessageFactory.newMessage(service, method);

//GEt name
message.putMessageParameter(IHelloService.SayHelloOperation.INPUT.NAME, args.get(IHelloService.SayHelloOperation.INPUT.NAME));

//Get salary
Integer integer = new Integer(args.get(IHelloService.SayHelloOperation.INPUT.SALARY));

//Put args
message.putMessageParameter(IHelloService.SayHelloOperation.INPUT.SALARY, integer);

//No transaction
message.setTransactionPolicy(TransactionPolicy.NO_TRANSACTION);

//No JPA, default use JPA
message.putMessageParameter(IMessageConstants.SERVICE_CALLER_USES_ENTITY_MANAGER_KEY, false);

return message;
}


}


You can look at the json-example from SVN , http://code.google.com/p/defne/source/browse/#svn/trunk/defne-samples/json-example

Enjoy!!!!


Web Site : http://code.google.com/p/defne/

SVN Site : http://code.google.com/p/defne/source/browse/

Maven Snapshot : https://oss.sonatype.org/content/repositories/snapshots/org/defne/

Defne Discussion : http://groups.google.com/group/defnedev

Published at DZone with permission of its author, Gurkan Erdogdu.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Jacek Furmankiewicz replied on Thu, 2010/07/15 - 9:08am

Oh God, not another me-too Java web framework.

I fail to see a single feature here that has not been done to death in X number of different Java web frameworks.

Really, if your web framework cannot beat Python Django admin interface in terms of productivity, you shouldn't be releasing it. That's the level of abstraction and productivity today's Java web frameworks should be trying to beat.

 

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.