Wednesday, December 16, 2009

Update Calendar Item using Exchange web services

Hi,

Here is a sample code which is used to update a calendar item with a particular entry id and change key. For each of the property we update, we need to set the URI pointing to that property in calendar item and the object with the updated property.

private boolean sendMeetingUpdate(String id, String key)
{
boolean errorOccurred = false;
try
{
//ItemChangeType calendarChange

UpdateItemType updateCalendarItem = UpdateItemType.Factory.newInstance();

updateCalendarItem.setSendMeetingInvitationsOrCancellations(CalendarItemUpdateOperationType.SEND_TO_ALL_AND_SAVE_COPY);
updateCalendarItem.setConflictResolution(ConflictResolutionType.ALWAYS_OVERWRITE);
updateCalendarItem.setMessageDisposition(MessageDispositionType.SAVE_ONLY);

//setting the item identifier
ItemIdType itemIdentifier = ItemIdType.Factory.newInstance();
itemIdentifier.setId(id);
itemIdentifier.setChangeKey(key);

ItemChangeType[] itemChangesArray = new ItemChangeType[1];
itemChangesArray[0] = ItemChangeType.Factory.newInstance();
itemChangesArray[0].setItemId(itemIdentifier);

//Object to hold the properties.
SetItemFieldType[] itemFieldChangesArray = new SetItemFieldType[1];

//Setting the path to subject

//Forming the update calendar Object
CalendarItemType calendarItemObj = CalendarItemType.Factory.newInstance();
calendarItemObj.setSubject("Update Subject");

itemFieldChangesArray[0] = SetItemFieldType.Factory.newInstance();
itemFieldChangesArray[0].setCalendarItem(calendarItemObj);

PathToUnindexedFieldType pathToSubjectObj = PathToUnindexedFieldType.Factory.newInstance();
pathToSubjectObj.setFieldURI(UnindexedFieldURIType.ITEM_SUBJECT);

FieldURIDocument fieldURIDoc = FieldURIDocument.Factory.newInstance();
fieldURIDoc.setFieldURI(pathToSubjectObj);

itemFieldChangesArray[0].setPath(pathToSubjectObj);

NonEmptyArrayOfItemChangeDescriptionsType nonEmptyArrayOfItemChangeDescriptionsTypeObj = NonEmptyArrayOfItemChangeDescriptionsType.Factory.newInstance();
nonEmptyArrayOfItemChangeDescriptionsTypeObj.setSetItemFieldArray(itemFieldChangesArray);
itemChangesArray[0].setUpdates(nonEmptyArrayOfItemChangeDescriptionsTypeObj);

NonEmptyArrayOfItemChangesType nonEmptyArrayOfItemChangesTypeObj = NonEmptyArrayOfItemChangesType.Factory.newInstance();
nonEmptyArrayOfItemChangesTypeObj.setItemChangeArray(itemChangesArray);
updateCalendarItem.setItemChanges(nonEmptyArrayOfItemChangesTypeObj);

UpdateItemDocument updateMeetingRequest = UpdateItemDocument.Factory.newInstance();
updateMeetingRequest.setUpdateItem(updateCalendarItem);

UpdateItemResponseDocument updateItemResponseDocument = null;
System.out.println("Soap Request = \n" + updateMeetingRequest.toString());

try
{
updateItemResponseDocument = exService.updateItem(updateMeetingRequest, null, null, null, getServerVersionDetails(), null);
}
catch (Exception e)
{
System.out.println("\nError while updating calendar=" + e.getMessage());
e.printStackTrace();
return false;
}

ArrayOfResponseMessagesType arrayOfResponseMessagesType = updateItemResponseDocument.getUpdateItemResponse().getResponseMessages();
ItemInfoResponseMessageType[] infoResponseMessageType = arrayOfResponseMessagesType.getUpdateItemResponseMessageArray();

for (ItemInfoResponseMessageType type : infoResponseMessageType)
{
System.out.println("\nSOAP Response xml=" + type.xmlText());
if (type.getResponseClass() == ResponseClassType.SUCCESS)
{
ItemIdType itemId = type.getItems().getCalendarItemArray(0).getItemId();
System.out.println(itemId.getId());
System.out.println(itemId.getChangeKey());
}
else
{
System.out.println("Error occcured while createing calendar item. response = "
+ type.getResponseClass());
errorOccurred = true;
}
}
}
catch (Exception e)
{
System.out.println("Error Occured while updating meeting request - " + "\n" + e.getMessage());
e.printStackTrace();
return false;
}

if (errorOccurred)
return false;
else
return true;
}

Sunday, November 22, 2009

Creating Exchange Service Stub using AXIS 2

I had a good learning experience migrating our calendering functionality from exchange server 2003 to exchange server 2007. And in this post, I have jotted out how to create a proper exchange service client stub using Axis 2.

Creation of client stub is not straight forward as it seems. It is because the stub generated by Axis 2 without any changes to auto generated stub code has one malformed element and as a result the SOAP request is not formed correctly.

The final list of steps I followed are below,

Step-1:
Download axis2- 1.5 from the net and unzip it.

Step-2: Download the Services.wsdl, types.xsd and messages.xsd from https://ExchangeServerURL/ews/Services.wsdl and place the same under the folder axis2- 1.5.

Step-3: In Services.wsdl file we need to add an XML element that defined the service. So add the following piece of code in the end just before the closure of wsdl:definition.

<wsdl:service name="ExchangeService">
    <wsdl:port name="ExchangeServicePort" binding="tns:ExchangeServiceBinding">
        <soap:address location="https://ExchangeServerURL/ews"/>
    </wsdl:port>
</wsdl:service>


Step-4: Execute the below from command prompt to generate the source files. The source files will get generated under axis2-1.5/ews directory.

C:\exchange\axis2-1.5>bin\wsdl2java -d xmlbeans -s -ss -g -o ews -uri Services.wsdl

Step-5: We need to manually change the class ChangeDescriptionTypeImpl in the package com.microsoft.schemas.exchange.services._2006.types.impl so that the XML is formed correctly for the UpdateItem request. The issue was with specifying the element that denotes the property that needs to be changed. The XML was generated with tag but the exchange server was expecting the element . So we need to change the variable PATH$0 in the class from

private static final javax.xml.namespace.QName PATH$0 = new javax.xml.namespace.QName("http://schemas.microsoft.com/exchange/services/2006/types", "Path");

    to

private static final javax.xml.namespace.QName PATH$0 = new javax.xml.namespace.QName("http://schemas.microsoft.com/exchange/services/2006/types", "FieldURI");

Step-6a: The above command also creates ant file that can be used to create the jar file (if ant is installed in windows).

    or

Step-6b: If ant is not available in windows, you can still create the jar file by manually setting the unix paths in the build.xml and running ant from unix.

Step-7: After running ant, the aar and jar file gets created in axis2-1.5\ews\build\lib directory and this can be added to class path and used in programming.

I the next post we will see how to send a mail using the stub we generated.

If you face any issues with the creation or using the stub, provide your questions here and I would be happy to help.

Sunday, May 24, 2009

iBatis Vs Hibernate

Hi All,

I did a research on what framework to choose for the DB layer of the application as I had to migrate one of my applications to use one of the popular frameworks available. I performed the research on the two most popular open source products - iBatis and Hibernate. I am listing down the features of each one of them below,

Hibernate :
Object <-> Relational mappingsIt provides three different O/R mapping strategies. It allows associating multiple objects to a single table row. It supports polymorphic associations, bidirectional associations and association filtering. It also provides support for basic collection types.
Hibernate query languageIt provides query language that uses objects instead of tables and makes it easy for a developer to write queries.
Improves PerformanceIt has a feature of loading the child objects in a hierarchy only when it is used called lazy loading. It also provides a scalable architecture. Connection pooling and prepared statement caching is also possible.


iBatis :
Data MapperIt allows the developer to map the result set to the class using XML. The result set can be either from a direct SQL or stored procedure.
Performance TuningSince iBatis gives the full control of the SQL query generated to the developer, it helps in performance tuning of the queries where complex joins are required to fetch the data.
Ease of MigrationSince it accepts native SQL and Stored procedures, it is easy to migrate to iBatis without much effort. The learning curve is less here as the developer just need to know about the mapping of result-set with class.


iBatis Vs Hibernate :

Friday, May 22, 2009

Struts 2.0

Hi All,

In this post I am going to brief about Struts 2.0 framework and how to configure it with the tomcat server.

Struts 2.0 is a simple MVC framework. It helps us in converting simple java class (POJO) into an action class that serves the requests. It helps us map the request parameters with the action class variables and also helps in validation of the input parameters without much coding. It provides the developer with lots of tag to handle the display of data in the web page with minimal coding. Struts 2.0 also supports ajax theme and this makes the page more dynamic with least amount of effort from the developer.

Now let us see how to configure Struts 2.0 with tomcat container. The download links are below,
Tomcat - http://tomcat.apache.org/download-55.cgi
Struts - http://struts.apache.org/download.cgi#struts216

The steps to be followed for configuring Structs are below,
1. Configure Tomcat's web.xml file to include Struts 2.0 filter.
2. Write a simple jsp page.
3. Write your simple action class.
4. Modify struts.xml (the controller) to define the action, its mapped class and the resultant Jsp (view).

web.xml Configuration :
We need to add the struts filter in web.xml so that all the requests coming to tomcat with ".action" should now be routed to struts framework. All other requests which contain .html, .gif etc will be taken care by server directly.

web.xml
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>

<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


JSP Page :
Before we create a jsp, we need to include the uri for struts tags. In the example below, we have used "<s:property value="message" />" to get the value that is set in the variable message in action class that is mapped to this jsp. Struts just invokes the getter of the variable to retrieve the value from the action class.

MyFirstView.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title> My First Struts Page </title>
</head>
<body>
<s:property value="message" />
</body>
</html>


Action Class :
Any java class can act as the request handler in struts, provided it has a public method that takes no parameters and has a String return type. The string that is returned by the method in action class will be used by struts to map to a particular jsp (as defined in struts.xml). If no method is specified in the action mapping, struts will transfer the control to "execute" method of the action class.

MyActionClass.java
package tutorial;
import com.opensymphony.xwork2.ActionSupport;
public class MyActionClass extends ActionSupport
{
public static final String MESSAGE = "Struts";
private String message;

public String execute() throws Exception
{
setMessage(MESSAGE);
return SUCCESS;
}

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

public String getMessage()
{
return message;
}
}


struts.xml Configuration :
struts.xml
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="tutorial" extends="struts-default">
<action name="HelloWorld"
class="tutorial.MyActionClass">
<result>/MyFirstView.jsp</result>
</action>
<!-- Add your actions here -->
</package>
</struts>


If you have any queries/comments, please post here and I will try to reply within a day.