Tag Archive 'java'

Jul 22 2008

JFace Binding

Published by under Eclipse,IT,Java

Recently I have started using JFace Binding. Unfortunately there are not many resources available on the web with non-trivial examples.

Let present example of master-detail view: a drop-down list and two text fields which display some details regarding option chosen from the list.

POJO Category. It contains two fields: name and description which will be displayed as details of the object chosen from the drop-down list:

import java.beans.PropertyChangeListener;
import java.io.Serializable;
 
/**
* Domain object representing category
*
*/
public class Category implements Serializable {
 
private static final long serialVersionUID = -5542167952605551865L;
 
private String name;
private String description;
 
/**
* Default constructor
*/
public Category() {
// Do nothing
}
 
/**
* Constructor
*
* @param name
*            name of a category
* @param description
*            description of a category
*/
public Category(String name, String description) {
this.name = name;
this.description = description;
}
 
/**
* @return the name
*/
public String getName() {
return name;
}
 
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
 
/**
* @return the description
*/
public String getDescription() {
return description;
}
 
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
}

Class of model that will be used to bind the data to the view:

import java.util.List;
 
/**
* Model for displaying categories
*
*/
public class CategoriesModel extends AbstractModelObject {
private List<Category> categories;
private IDataManager dataManager;
private Category category;
 
/**
* The constructor
*/
public CategoriesModel() {
this.dataManager = Activator.getDataManager();
this.categories = this.dataManager.getAllCategories();
}
 
/**
* @return the category
*/
public Category getCategory() {
return this.category;
}
 
/**
* @param category
*            the category to set
*/
public void setCategory(Category category) {
this.category = category;
}
 
/**
* @return the categories
*/
public List<Category> getCategories() {
return categories;
}
 
/**
* @param categories the categories to set
*/
public void setCategories(List<Category> categories) {
this.categories = categories;
}
}

Class of view (in this case it is Eclipse View containing managed form):

import java.util.logging.Logger;
 
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.ManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.part.ViewPart;
 
/**
* Allows to view list of categories and their details
*
*/
public class CategoryView extends ViewPart {
 
private Logger logger = Logger.getLogger(CategoryView.class.getName());
 
private static final String FORM_TITLE = Messages
.getString("category.view.form.title");
 
private FormToolkit formToolkit;
 
private CategoriesModel model;
private Text nameText;
private Text descriptionText;
private ComboViewer categoriesComboViewer;
private DataBindingContext dbc;
 
/**
* {@inheritDoc}
*/
@Override
public void createPartControl(Composite parent) {
model = new CategoriesModel();
 
ManagedForm mForm = new ManagedForm(parent);
ScrolledForm scrolledForm = mForm.getForm();
FormToolkit formToolkit = mForm.getToolkit();
Composite formBody = scrolledForm.getBody();
formToolkit.decorateFormHeading(scrolledForm.getForm());
scrolledForm.setText(FORM_TITLE);
formBody.setLayout(new GridLayout(2, true));
 
categoriesComboViewer = new ComboViewer(formBody, SWT.DROP_DOWN
| SWT.READ_ONLY);
GridData comboGridData = new GridData();
comboGridData.horizontalSpan = 2;
comboGridData.horizontalAlignment = GridData.FILL;
categoriesComboViewer.getCombo().setLayoutData(comboGridData);
 
nameText = formToolkit.createText(formBody, "", SWT.NONE);
GridData nameGridData = new GridData();
nameGridData.horizontalSpan = 2;
nameGridData.horizontalAlignment = GridData.FILL;
nameText.setLayoutData(nameGridData);
 
descriptionText = formToolkit.createText(formBody, "", SWT.MULTI);
GridData textGridData = new GridData();
textGridData.horizontalSpan = 2;
textGridData.horizontalAlignment = GridData.FILL;
textGridData.heightHint = 100;
descriptionText.setLayoutData(textGridData);
 
formToolkit.paintBordersFor(formBody);
bindData();
}
 
/**
* {@inheritDoc}
*/
@Override
public void setFocus() {
// Do nothing
}
 
/**
* This method binds the value from UI layer to the model object
*/
protected void bindData() {
dbc = new DataBindingContext();
 
// Seting content provider for combo viewer
ObservableListContentProvider categoryViewerContentProvider = new ObservableListContentProvider();
categoriesComboViewer.setContentProvider(categoryViewerContentProvider);
IObservableMap[] attributeMaps = BeansObservables.observeMaps(
categoryViewerContentProvider.getKnownElements(),
Category.class, new String[] { "name" });
categoriesComboViewer.setLabelProvider(new ObservableMapLabelProvider(
attributeMaps));
categoriesComboViewer.setInput(new WritableList(model.getCategories(),
Category.class));
 
// Observing changes in selection in combo viewer
IObservableValue selection = ViewersObservables
.observeSingleSelection(categoriesComboViewer);
 
// Observing the properties of the current selection
IObservableValue detailNameObservable = BeansObservables
.observeDetailValue(Realm.getDefault(), selection, "name",
String.class);
 
IObservableValue detailDescriptionObservable = BeansObservables
.observeDetailValue(Realm.getDefault(), selection,
"description", String.class);
 
// Binding the Text widgets to the name and description details
// (selection's properties).
dbc.bindValue(SWTObservables.observeText(nameText, SWT.None),
detailNameObservable, new UpdateValueStrategy(false,
UpdateValueStrategy.POLICY_NEVER), null);
 
dbc.bindValue(SWTObservables.observeText(descriptionText, SWT.None),
detailDescriptionObservable, new UpdateValueStrategy(false,
UpdateValueStrategy.POLICY_NEVER), null);
}
 
/**
* {@inheritDoc}
*/
public void dispose() {
if (formToolkit != null) {
formToolkit.dispose();
}
super.dispose();
}
}

AbstractModelObject which provides methods required by JFace Binding (it’s not checked on compilation level):

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
 
/**
* Provides minimal JavaBeans support for model objects
*
*/
public abstract class AbstractModelObject {
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
this);
 
/**
* @param listener
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
 
/**
* @param propertyName
* @param listener
*/
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}
 
/**
* @param listener
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
 
/**
* @param propertyName
* @param listener
*/
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(propertyName,
listener);
}
 
/**
*
* @param propertyName
* @param oldValue
* @param newValue
*/
protected void firePropertyChange(String propertyName, Object oldValue,
Object newValue) {
propertyChangeSupport.firePropertyChange(propertyName, oldValue,
newValue);
}
}

4 responses so far

Dec 17 2007

Netbeans 6.0 Mobility – FileBrowser

Published by under IT,Java

Netbeans 6.0 gives really nice support for developing Java Micro Edition applications. It provides some useful classes which are not part of standard JME profiles.
One of them is class: org.netbeans.microedition.lcdui.pda.FileBrowser.
It provides file browser for mobile phone implementing JSR-75. It looks fine but there is a bug in it. Method getSelectedFileURL() returns incorrect value, e.g.: file:///E:/myfolder//myfile.mp3 instead of file:///E:/myfolder/myfile.mp3
Removing manually last extra slash fixes the problem.

One response so far

Sep 25 2007

Spring remoting quickstart

Published by under IT,Java

I have spent a lot of time on configuring Spring remoting properly (mostly because of problems with DTD).
To expose business logic via for example XFire Web Services we have to define context and listeners in web.xml, example:

<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!DOCTYPE web-app
PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN”

“http://java.sun.com/dtd/web-app_2_3.dtd”>
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>
<servlet>
<servlet-name>XFireServlet</servlet-name>
<servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/servlet/XFireServlet/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>

Configuration of beans that are going to be exposed via WS is stored in separate file, in this case in applicationContext.xml. Example of the content of the file:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans-2.0.dtd”>
<beans>
<bean class=”org.springframework.web.servlet.handler.SimpleUrlHandlerMapping”>
<property name=”urlMap”>
<map>
<entry key=”/WorkflowRegister”>
<ref bean=”workflowRegister”/>
</entry>
</map>
</property>
</bean>
<bean id=”workflowRegister” class=”org.codehaus.xfire.spring.remoting.XFireExporter”>
<property name=”serviceFactory”>
<ref bean=”xfire.serviceFactory”/>
</property>
<property name=”xfire”>
<ref bean=”xfire”/>
</property>
<property name=”serviceBean”>
<ref bean=”worklfowRegisterBean”/>
</property>
<property name=”serviceClass”>
<value>pl.edu.agh.gemini.adds.core.IWorkflowRegister</value>
</property>
</bean>
<bean id=”worklfowRegisterBean” class=”pl.edu.agh.gemini.adds.core.WorkflowRegister” factory-method=”getInstance” />
<import resource=”classpath:org/codehaus/xfire/spring/xfire.xml”/>
</beans>

As you can see defining new WS which is based on already implemented bean requires just few lines of XML. Business logic is totally separated from the way of exposing it. No changes are required in logic to expose it as Web Service! Also changing transport layer from XFire to e.g. Burlap/Hessian/RMI is just a matter of configuration in those two files.

Dependencies for Spring remoting (part of Maven pom.xml):

<dependencies>
<dependency>
<groupId>pl.edu.agh.gemini.adss</groupId>
<artifactId>adsscore</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>pl.edu.agh.gemini.adss</groupId>
<artifactId>adsscoreapi</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-remoting</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.codehaus.xfire</groupId>
<artifactId>xfire-jaxb2</artifactId>
<version>1.2-RC</version>
</dependency>
<dependency>
<groupId>org.codehaus.xfire</groupId>
<artifactId>xfire-spring</artifactId>
<version>1.2-RC</version>
</dependency>
<dependency>
<groupId>org.codehaus.xfire</groupId>
<artifactId>xfire-java5</artifactId>
<version>1.2-RC</version>
</dependency>
</dependencies>

Application can be simply deployed as war file in servlet container (e.g. Tomcat), no J2EE application server is required.

Have fun with Spring remoting!

No responses yet

May 04 2007

Injecting EJB 3.0 beans into Struts 2.0

Published by under IT,Java

EJB 3.0 provides easy bean injection. While developing web layer in Struts 2.0 you can use similar mechanism as well. Struts 2.0 is using Spring libraries for implementing Inversion of Control design pattern.

EJB 3.0 is based on using Java 1.5 annotations. It simplifies deployment process.

Let define example Session Bean.

@Stateless(mappedName=”ejb/EmployeeManager”)
public class EmployeeManagerSB implements IEmployeeManager {

public Long createAccount(String loginName) {
// Implementation of creating an account…
}

}

It implements interface:

@Remote
@Local

public interface IEmployeeManager {

Long createAccount(String loginName);

}

To use EmployeeManager session bean in Struts 2.0 reference to this object has to be retrieved.

Let define Struts action class which will use EmployeeManager session bean.

@Validation()
public class NewEmployeeAction extends ActionSupport {

private IEmployeeManager employeeManager;
private String loginName;
private long id;
private String redirectURL;

public String execute() throws Exception {
Long id = this.employeeManager.createAccount(this.loginName);
this.setId(id.longValue());
return SUCCESS;
}

public IEmployeeManager getEmployeeManager() {
return employeeManager;
}

public void setEmployeeanager(IEmployeeManager employeeManager) {
this.employeeManager = employeeManager;
}

public String getLoginName() {
return loginName;
}

@RequiredStringValidator(message = “Please enter a login name”, trim = true)
public void setLoginName(String loginName) {
this.loginName = loginName;
}

public long getId() {
return id;
}

public String getRedirectURL() {
return redirectURL;
}

public void setRedirectURL(String redirectURL) {
this.redirectURL = redirectURL;
}

}

Framework is taking care of injecting proper object while creating this action object. In Struts 2.0 the only thing that has to be done to do this is defining it in applicationContext.xml configuration file.

<jee:jndi-lookup id=”employeeManager” name=”ejb/EmployeeManager“>

<bean id=”newEmployeeAction” class=”pl.edu.agh.sius2007.jspynet.struts.NewEmployeeAction”>
<property name=”employeeManager” ref=”employeeManager”>
</bean>

The only configuration in Struts is defining two beans.

  • employeeManager which will be retrieved from JNDI;
  • newEmployeeAction which is Struts action.

employeeManager bean will be retrieved automatically and injected into newEmployeeAction.

No responses yet