Consuming Exchange Web Services with Java using Glassfish and Metro: Creating an ItemType Data Access Object

In my previous article, Consuming Exchange Web Services with Java using Glassfish and Metro: Using ExchangeServicePortType with Authentication Credentials, I went through cleaning up the creation of Exchange Web Service stubs. Then we put our generated code to good use and created an authenticator to return an ExchangeServicePortType with authentication credentials. This ExchangeServicePortType will serve the the base for all future SOAP requests. Each method of ExchangeServicePortType generates the corresponding SOAP request and returns Java objects populated by the SOAP response.

However, due to the xsi:nil error mentioned last article, we will be overloading each method of the ExchangeServicePortType. There may be other techniques out there, please comment and share them with me. This is the most straightforward way I've found to do it though.

At the end of this article we will create a data access object which returns a List of ItemType objects representing the items in your Inbox.

Method Overloading findItem(...) in ExchangeServicePortType

When the ExchangeServicePortType interface generates its SOAP request, any parameters missing from ExchangeServicePortType methods will not be included as attributes in the SOAP request. So, because we can't pass null parameters to the findItem(...) method, we can overload it so that it does not require the parameters causing problems for us.

The findItem(...) method generated for us by JAX-WS and the WSDL has 7 parameters:

  1. FindItemType request (required) -- The FindItemType object that contains all the information about our request.
  2. ExchangeImpersonationType impersonation (optional) -- If the account you authenticated with has impersonation privileges, you can use this to impersonate other users.
  3. SerializedSecurityContextType s2SAuth (optional) -- The MSDN documentation states that “The SerializedSecurityContextType class is used in the SOAP header for token serialization in server-to-server authentication. Token serialization is not supported.” So does “not supported” mean this doesn't work or Microsoft doesn't support it? At any rate, I've never used it and I don't really know what it means.
  4. String mailboxCulture (required) -- A string representing the language of your account's mailbox.
  5. RequestServerVersion requestVersion (required) -- A string representing the server version you intend to be requesting to.
  6. Holder serverVersion (required) -- A holder for the server's response about what server version it is.
  7. Holder findItemResult (required) -- This is what you're after. The server's response for the items that meet your findItem criteria.

So unless you're making an impersonation request or a request with SerializedSecurityContextType, you really only need a findItem(...) method with 5 parameters. So we will be overloading findItem(...) with 3 new methods:

  1. findFolder(request, mailboxCulture, requestVersion, findFolderResult, serverVersion)
  2. findFolder(request, impersonation, mailboxCulture, requestVersion, findFolderResult, serverVersion)
  3. findFolder(request, s2SAuth, mailboxCulture, requestVersion, findFolderResult, serverVersion)

This way we get the method we want (and will use most often) that only needs 5 parameters. However, in the event someone want to use impersonation or SerializedSecurityContextType, those methods are available as well.

Find the findItem(...) method in ExchangeServicePortType. It should look some thing like:

    /**
     * 
     * @param findItemResult
     * @param request
     * @param serverVersion
     * @param impersonation
     * @param requestVersion
     * @param mailboxCulture
     * @param s2SAuth
     */
    @WebMethod(operationName = "FindItem", action = "http://schemas.microsoft.com/exchange/services/2006/messages/FindItem")
    public void findItem(
        @WebParam(name = "FindItem", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages", partName = "request")
        FindItemType request,
        @WebParam(name = "ExchangeImpersonation", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "Impersonation")
        ExchangeImpersonationType impersonation,
        @WebParam(name = "SerializedSecurityContext", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "S2SAuth")
        SerializedSecurityContextType s2SAuth,
        @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
        @WebParam(name = "MailboxCulture", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "MailboxCulture")
        String mailboxCulture,
        @WebParam(name = "RequestServerVersion", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "RequestVersion")
        RequestServerVersion requestVersion,
        @WebParam(name = "FindItemResponse", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages", mode = WebParam.Mode.OUT, partName = "FindItemResult")
        Holder findItemResult,
        @WebParam(name = "ServerVersionInfo", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, mode = WebParam.Mode.OUT, partName = "ServerVersion")
        Holder serverVersion);

Replace it with the following code so there are four findItem(...) methods:

    /**
     * 
     * @param findItemResult
     * @param request
     * @param serverVersion
     * @param impersonation
     * @param requestVersion
     * @param mailboxCulture
     * @param s2SAuth
     */
    @WebMethod(operationName = "FindItem", action = "http://schemas.microsoft.com/exchange/services/2006/messages/FindItem")
    public void findItem(
        @WebParam(name = "FindItem", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages", partName = "request")
        FindItemType request,
        @WebParam(name = "ExchangeImpersonation", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "Impersonation")
        ExchangeImpersonationType impersonation,
        @WebParam(name = "SerializedSecurityContext", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "S2SAuth")
        SerializedSecurityContextType s2SAuth,
        @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
        @WebParam(name = "MailboxCulture", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "MailboxCulture")
        String mailboxCulture,
        @WebParam(name = "RequestServerVersion", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "RequestVersion")
        RequestServerVersion requestVersion,
        @WebParam(name = "FindItemResponse", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages", mode = WebParam.Mode.OUT, partName = "FindItemResult")
        Holder findItemResult,
        @WebParam(name = "ServerVersionInfo", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, mode = WebParam.Mode.OUT, partName = "ServerVersion")
        Holder serverVersion);
    
    /**
     * 
     * @param findItemResult
     * @param request
     * @param serverVersion
     * @param requestVersion
     * @param mailboxCulture
     */
    @WebMethod(operationName = "FindItem", action = "http://schemas.microsoft.com/exchange/services/2006/messages/FindItem")
    public void findItem(
        @WebParam(name = "FindItem", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages", partName = "request")
        FindItemType request,
        @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
        @WebParam(name = "MailboxCulture", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "MailboxCulture")
        String mailboxCulture,
        @WebParam(name = "RequestServerVersion", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "RequestVersion")
        RequestServerVersion requestVersion,
        @WebParam(name = "FindItemResponse", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages", mode = WebParam.Mode.OUT, partName = "FindItemResult")
        Holder findItemResult,
        @WebParam(name = "ServerVersionInfo", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, mode = WebParam.Mode.OUT, partName = "ServerVersion")
        Holder serverVersion);
    
    /**
     * 
     * @param findItemResult
     * @param request
     * @param serverVersion
     * @param impersonation
     * @param requestVersion
     * @param mailboxCulture
     */
    @WebMethod(operationName = "FindItem", action = "http://schemas.microsoft.com/exchange/services/2006/messages/FindItem")
    public void findItem(
        @WebParam(name = "FindItem", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages", partName = "request")
        FindItemType request,
        @WebParam(name = "ExchangeImpersonation", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "Impersonation")
        ExchangeImpersonationType impersonation,
        @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
        @WebParam(name = "MailboxCulture", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "MailboxCulture")
        String mailboxCulture,
        @WebParam(name = "RequestServerVersion", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "RequestVersion")
        RequestServerVersion requestVersion,
        @WebParam(name = "FindItemResponse", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages", mode = WebParam.Mode.OUT, partName = "FindItemResult")
        Holder findItemResult,
        @WebParam(name = "ServerVersionInfo", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, mode = WebParam.Mode.OUT, partName = "ServerVersion")
        Holder serverVersion);
    
    /**
     * 
     * @param findItemResult
     * @param request
     * @param serverVersion
     * @param requestVersion
     * @param mailboxCulture
     * @param s2SAuth
     */
    @WebMethod(operationName = "FindItem", action = "http://schemas.microsoft.com/exchange/services/2006/messages/FindItem")
    public void findItem(
        @WebParam(name = "FindItem", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages", partName = "request")
        FindItemType request,
        @WebParam(name = "SerializedSecurityContext", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "S2SAuth")
        SerializedSecurityContextType s2SAuth,
        @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
        @WebParam(name = "MailboxCulture", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "MailboxCulture")
        String mailboxCulture,
        @WebParam(name = "RequestServerVersion", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, partName = "RequestVersion")
        RequestServerVersion requestVersion,
        @WebParam(name = "FindItemResponse", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/messages", mode = WebParam.Mode.OUT, partName = "FindItemResult")
        Holder findItemResult,
        @WebParam(name = "ServerVersionInfo", targetNamespace = "http://schemas.microsoft.com/exchange/services/2006/types", header = true, mode = WebParam.Mode.OUT, partName = "ServerVersion")
        Holder serverVersion);

Now let's create a data access object which retrieves items from the Inbox.

Creating an ItemType Data Access Object

Like my previous article, I'm going to let the Java class source code speak for itself. I've commented it along the way as a sort of inline tutorial:

package name.reidmiller.exchange.dao;

import javax.xml.bind.JAXBElement;
import javax.xml.ws.Holder;

import com.microsoft.schemas.exchange.services._2006.messages.*;
import com.microsoft.schemas.exchange.services._2006.types.*;
import java.util.*;
import name.reidmiller.exchange.util.ExchangeEnvironmentSettings;

/**
 * Data access object related to operations involving ItemType objects.
 * 
 * @author Reid Miller
 */
public class ItemTypeDAO {
    private ExchangeEnvironmentSettings exchangeEnvironmentSettings = new ExchangeEnvironmentSettings();

    /**
     * Gets the Exchange Items for a desired folder and returns them as a
     * List of ItemType objects.
     * 
     * This method was adopted from C# documentatino at 
     * http://msdn.microsoft.com/en-us/library/bb508824.aspx
     * 
     * At this point the method is very basic to illustrate concepts. From 
     * here it's not too much of a stretch refactor this method to retreive 
     * arbitrary FolderIdType, integrate pagination, and run a search over 
     * and arbitrary folder. Exchange Web Services makes all these tasks 
     * pretty easy actually.
     * 
     * @param port
     * @return List
     */
    public List getFolderItems(ExchangeServicePortType port) {
        // Tell it you only want to look in the Inbox folder by using the 
        // DistinguishedFoldIdType.INBOX constant.
        final DistinguishedFolderIdType distinguishedFolderIdType = new DistinguishedFolderIdType();
        distinguishedFolderIdType.setId(DistinguishedFolderIdNameType.INBOX);

        // We could build a NonEmptyArrayOfBaseFolderIdsType object to search 
        // over multiple folders, but for now we will only add the Inbox 
        // DistinguishedFolderIdType from above.
        NonEmptyArrayOfBaseFolderIdsType nonEmptyArrayOfBaseFolderIdsType = new NonEmptyArrayOfBaseFolderIdsType();
        nonEmptyArrayOfBaseFolderIdsType.getFolderIdOrDistinguishedFolderId().add(distinguishedFolderIdType);

        // Tell Exchange you want the response objects to contain all the 
        // ItemType properties available to a findItem request. See limitations 
        // of findItem requests at http://msdn.microsoft.com/en-us/library/bb508824.aspx 
        final ItemResponseShapeType itemResponseShapeType = new ItemResponseShapeType();
        itemResponseShapeType.setBaseShape(DefaultShapeNamesType.ALL_PROPERTIES);

        // Now make use of both the objects from above to construct a minimal 
        // FindItemType request to be sent.
        FindItemType request = new FindItemType();
        request.setTraversal(ItemQueryTraversalType.SHALLOW); // SHALLOW means it doesn't look for "soft deleted" items.
        request.setItemShape(itemResponseShapeType);
        request.setParentFolderIds(nonEmptyArrayOfBaseFolderIdsType);

        // Create a FindItemResponseType to be sent with the SOAP request. The 
        // Holder is filled with the response from Exchange and sent back through
        // the SOAP response.
        FindItemResponseType findItemResponse = new FindItemResponseType();
        Holder findItemResult = new Holder(findItemResponse);

        // Make SOAP request for ItemTypes to EWS
        port.findItem(request, exchangeEnvironmentSettings.getMailboxCulture(), exchangeEnvironmentSettings.getRequestServerVersion(), findItemResult, exchangeEnvironmentSettings.getServerVersionInfoHolder());

        // Create List of ItemTypes to be returned by the method
        List items = new ArrayList();

        // Evaluate the FindItemResponseType sent back by Exchange
        FindItemResponseType response = (FindItemResponseType) findItemResult.value;
        ArrayOfResponseMessagesType arrayOfResponseMessagesType = response.getResponseMessages();
        List responseMessageTypeList = arrayOfResponseMessagesType.getCreateItemResponseMessageOrDeleteItemResponseMessageOrGetItemResponseMessage(); // Note: Best method name... ever!

        // Response is a List of JAXBElement objects. Iterate through them
        Iterator responseMessagesIterator = responseMessageTypeList.iterator();

        // In this basic example, there's only one response message 
        // (JAXBElement) from Exchange.
        while (responseMessagesIterator.hasNext()) {
            JAXBElement jaxBElement = (JAXBElement) responseMessagesIterator.next();
            FindItemResponseMessageType findItemResponseMessageType = (FindItemResponseMessageType) jaxBElement.getValue();
            FindItemParentType findItemParentType = findItemResponseMessageType.getRootFolder();

            // FindItemParentType "Contains the results of a search of a single 
            // root folder during a FindItem operation."
            // http://msdn.microsoft.com/en-us/library/microsoft.servicemodel.channels....
            // 
            // If it is null (empty) then the folder does not contain any elements
            if (findItemParentType != null) {
                // Our one response message contained a FindItemParentType with
                // an ArrayOfRealItemsType (an array of ItemTypes)
                ArrayOfRealItemsType arrayOfRealItemsType = findItemParentType.getItems();
                List itemList = arrayOfRealItemsType.getItemOrMessageOrCalendarItem();
                
                // Iterate through the List of ItemTypes.
                Iterator itemListIter = itemList.iterator();
                while (itemListIter.hasNext()) {
                    ItemType itemType = (ItemType) itemListIter.next();
                    
                    // Watch the console, the subject for each item will stream
                    // by, evidence that our List is being populated.
                    System.out.println(itemType.getSubject());
                    
                    items.add(itemType);
                }
            }
            else {
                // TODO: Handle failed requests and empty responses. I'm 
                // glossing over this for now.
            }
        }

        return items;
    }
}

You'll notice that at the start of the ItemTypeDAO I instantiate a class called ExchangeEnvironmentSettings. This is a utility class I created to make the formation of future ExchangeServicePortType requests much easier. Below is the the ExchangeEnvironmentSettings class.

package name.reidmiller.exchange.util;

import com.microsoft.schemas.exchange.services._2006.types.*;
import javax.xml.ws.Holder;

/**
 * A utility class to make forming ExchangeServicePortType requests easier.
 * 
 * @author Reid Miller
 */
public class ExchangeEnvironmentSettings {
    /**
     * Get the mailbox culture "en-US" to keep things simple for now.
     * 
     * @return String
     */
    public String getMailboxCulture(){
        String mailboxCulture = "en-US";
        return mailboxCulture;
    }

    /**
     * A Holder that holds the server's response for what server version 
     * identifies iteself as.
     * 
     * @return Holder
     */
    public final Holder getServerVersionInfoHolder(){
        final ServerVersionInfo serverVersionInfo = new ServerVersionInfo();
        final Holder serverVersion = new Holder(serverVersionInfo);
        return serverVersion;
    }
	
    /**
     * Creates a RequestServerVersion object that states we're looking to speak 
     * with an Exchange 2007 Service Pack 1 server.
     * 
     * @return RequestServerVersion
     */
    public final RequestServerVersion getRequestServerVersion(){
        final RequestServerVersion requestVersion = new RequestServerVersion();
        requestVersion.setVersion(ExchangeVersionType.EXCHANGE_2007_SP_1);
        return requestVersion;
    }
}

Let's modify our ExchangeDevelopmentTest class from the last article to do a quick test of the new functionality. That class should look like:

package name.reidmiller.exchange.util;

import com.microsoft.schemas.exchange.services._2006.messages.ExchangeServicePortType;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import name.reidmiller.exchange.dao.ItemTypeDAO;

/**
 * Throw-away class for doing quick tests of features and classes during 
 * development.
 * 
 * @author Reid Miller
 */
public class ExchangeDevelopmentTest {
    /**
     * Main method so we can quickly test things.
     * @param args
     */
    public static void main (String[] args) {
        ExchangeAuthenticator exchangeAuthenticator = new ExchangeAuthenticator();

        // Print statement so we can easily see where our statements start in the Java console.
        System.out.println("Let's get started!");

        try {
            // Create a URL object which points at the .wsdl we deployed in the previous step.
            URL wsdlURL = new URL("http://localhost:8080/ExchangeWebServices/exchange.wsdl");
            // Call to the class we just created to return an ExchangeServicePortType with authentication credentials.
            ExchangeServicePortType port = exchangeAuthenticator.getExchangeServicePort("username", "password", "DOMAIN", wsdlURL);
            
            // Prints out the default toString() for the ExchangeServicePortType.
            System.out.println(port.toString());
            
            // Test out the new ItemTypeDAO functionality.
            ItemTypeDAO itemTypeDAO = new ItemTypeDAO();
            itemTypeDAO.getFolderItems(port);
        } catch (MalformedURLException ex) {
            // Catch any errors that may occur.
            Logger.getLogger(ExchangeDevelopmentTest.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Run your code

Just like the previous articles, to run the code:

  1. Using the “Projects” column on the left-hand side, find the package you created ExchangeDevelopmentTest in. Right-click on ExchangeDevelopmentTest.java and select “Run”.

In the Java console below you should see the subject lines of the email in your Inbox printed out on each line.

Conclusion

Now that you've coded an Exchange Web Service request from start to finish, a lot of the MSDN documentation should start to make sense. I would recommend their technical article series, as there are a lot of C# examples that are easily translatable into Java. Hopefully the timespan between this article and my next will not be so long. In my next article I will be covering the creation of a simple MessageType email message.

23 Comments

findItem error

Hi Reid,
I'm looking to build a miniature exchange client, as so I appreciate what you've posted here.
When I get to the findItem line of the ItemTypeDAO, I get an unauthorized error. Is this because the wsdl is behind an authentication realm, eg. check https://mail02.ndc.nasa.gov/ews/Exchange.asmx?

port.findItem(request, exchangeEnvironmentSettings.getMailboxCulture(), exchangeEnvironmentSettings.getRequestServerVersion(), findItemResult, exchangeEnvironmentSettings.getServerVersionInfoHolder());
com.sun.xml.internal.ws.client.ClientTransportException: request requires HTTP authentication: Unauthorized

Thanks,
Dave

Still the problem with 401 unauthorized

Hi Reid,
I read your series of articels and since I am new to the Exchange World I really enjoyed it!!! I followed your tutorial and also the hint you already gave to the 401 - Unauthorized error, but I still get this error. My coding looks like this:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ExchangeAuthenticator exchangeAuthenticator = new ExchangeAuthenticator();
response.getWriter().write("Let's get started!");
try {
Authenticator.setDefault(new RetrieveWSDLAuthenticator("domain\\user", "password"));
// Create a URL object which points at the .wsdl we deployed in the previous step.
URL wsdlURL = new URL("http://:/ExchangeWsClient/wsdl/Services.wsdl");
// Call to the class we just created to return an ExchangeServicePortType with authentication credentials.
ExchangeServicePortType port = exchangeAuthenticator.getExchangeServicePort("user", "password", "domain", wsdlURL);
// Prints out the default toString() for the ExchangeServicePortType.
response.getWriter().write(port.toString());
// Test out the new ItemTypeDAO functionality.
ItemTypeDAO itemTypeDAO = new ItemTypeDAO();
itemTypeDAO.getFolderItems(port);
response.getWriter().write("ItemDAO successfully executed: " + itemTypeDAO.getFolderItems(port).size());
response.getWriter().write(itemTypeDAO.toString());
} catch (MalformedURLException ex) {
// Catch any errors that may occur.
Logger.getLogger(ExchangeDevelopmentTest.class.getName()).log(Level.SEVERE, null, ex);
}
javax.xml.ws.WebServiceException: Invalid Response code (401). Server /EWS/exchange.asmx> returned message .
at com.sap.engine.services.webservices.espbase.client.jaxws.core.WSInvocationHandler.processTransportBindingCall(WSInvocationHandler.java:173)
at com.sap.engine.services.webservices.espbase.client.jaxws.core.WSInvocationHandler.invokeSEISyncMethod(WSInvocationHandler.java:120)
at com.sap.engine.services.webservices.espbase.client.jaxws.core.WSInvocationHandler.invokeSEIMethod(WSInvocationHandler.java:83)
at com.sap.engine.services.webservices.espbase.client.jaxws.core.WSInvocationHandler.invoke(WSInvocationHandler.java:64)
at $Proxy2066.findItem(Unknown Source)

The error happens in this line:
port.findItem(request, exchangeEnvironmentSettings.getMailboxCulture(),
exchangeEnvironmentSettings.getRequestServerVersion(), findItemResult,
exchangeEnvironmentSettings.getServerVersionInfoHolder());

When I access the Services.wsdl from my Browser on the exchange server, I get a username/password prompt on Firefox while on IE I am not even asked for a password, I just get a: "Internet Explorer cannot display the webpage". Might this be the problem?
It would be very nice if you have any ideas! Regards,
Jan

Re: Still the problem with 401 unauthorized

I ran into the same issue before and never resolved it. The same code would run flawlessly in a Java app, but fail with the 401 authentication error in a servlet. It would seem that there is a strange environment issue in attempting to run the code from a servlet context. Good luck getting a fix.

Search functinality

javax.xml.ws.soap.SOAPFaultException: An internal server error occurred.
at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException

1. Do you have any idea what might be going on?

I tried to search message with subject partial string , but i am getting erro.
can share me some code to seach message in Inbox folder based on subject or from address or by date.
I will appreciate your immediate help.

Thanks,
Cara San

modified Services.wsdl

Hi Reid,
Thanks for the article and helpful comments. I am running into the same 401 error which is resolved by using RetrieveWSDLAuthenticator class. Now I'm running into the "no service definition" problem you predict. I have modified my local version of Services.wsdl and generated java class using wsimport. My question is do I need to deploy the modified version of Services.wsdl on to the exchange server?
Zhao

Using RestrictionType

Reid,
Off to my next issue. I'm looking to filter requests through a RestrictionType filter, namely I'm interested in calendar events around a date window http://msdn.microsoft.com/en-us/library/aa563791.aspx. Here is what I've done:

After creating the request in your ItemTypeDAO class, I put this:
ExchangeFilter filter = new ExchangeFilter();
RestrictionType rt = filter.getFilter();
request.setRestriction(rt);

Where the ExchangeFilter class follows:
public class ExchangeFilter {
public ExchangeFilter() {
}

public RestrictionType getFilter() {
try {
ObjectFactory factory = new ObjectFactory();

PathToUnindexedFieldType puf1 = factory.createPathToUnindexedFieldType();
puf1.setFieldURI(UnindexedFieldURIType.ITEM_DATE_TIME_RECEIVED);
JAXBElement path1 = factory.createPath(puf1);

FieldURIOrConstantType fuct1 = factory.createFieldURIOrConstantType();
ConstantValueType cvt1 = factory.createConstantValueType();
cvt1.setValue("2009-03-02T00:00:00.000Z");
fuct1.setConstant(cvt1);

IsGreaterThanOrEqualToType gtet = new IsGreaterThanOrEqualToType();
gtet.setPath(path1);
gtet.setFieldURIOrConstant(fuct1);

PathToUnindexedFieldType puf2 = factory.createPathToUnindexedFieldType();
puf2.setFieldURI(UnindexedFieldURIType.ITEM_ITEM_CLASS);
FieldURIOrConstantType fuct3 = factory.createFieldURIOrConstantType();
ConstantValueType cvt3 = factory.createConstantValueType();
cvt3.setValue("IPM.Schedule.Meeting.Request");
fuct3.setConstant(cvt3);
IsEqualToType et = factory.createIsEqualToType();
et.setPath(factory.createPath(puf2));
et.setFieldURIOrConstant(fuct3);

RestrictionType rt = factory.createRestrictionType();
rt.setSearchExpression(factory.createIsEqualTo(et));
// rt.setSearchExpression(factory.createIsGreaterThanOrEqualTo(gtet));
return rt;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

You can see I have two filters here, a date filter and a Schedule Meeting Request filter. Both of these filters give the same error, one that looks like your nil error that you wrestled with on the findItem method. Below find the stack trace obtained during the findItem method call:

javax.xml.ws.soap.SOAPFaultException: An internal server error occurred.
at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:189)
at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:122)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)
at $Proxy40.findItem(Unknown Source)
at gov.nasa.hq.ews.ItemTypeDAO.getFolderItems(ItemTypeDAO.java:73)
at gov.nasa.hq.ews.ExchangeDevelopmentTest.main(ExchangeDevelopmentTest.java:35)
Process exited.

1. Do you have any idea what might be going on?
2. How do I output the soap request for inspection?

I guess I need to take some time and learn more about consuming web services using JAXB. But in the mean time, any ideas from you will be most appreciated
Thanks,
Dave

Getting error in findItem when search message based on subject

javax.xml.ws.soap.SOAPFaultException: An internal server error occurred.
at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException

1. Do you have any idea what might be going on?

I tried to search message with subject partial string , but i am getting erro.
can share me some code to seach message in Inbox folder based on subject or from address or by date.
I will appreciate your immediate help.

Thanks,
Cara San

findItem overloaded

Hi!
I swear I followed your tutorial. I´ve overloaded findItem(), however I am still getting the exception: "The request failed schema validation: If the 'nillable' attribute is false in the schema, the 'xsi:nil' attribute must not be present in the instance"

Did I miss something?

Thanks!

I'm getting the following

I'm getting the following error:

Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target error.

Any ideas!

Re: I'm getting the following - Another question

I was getting the same SSLHandshakeException. It looks like your server has an open key. This can help you http://dreamingthings.blogspot.com/2006/12/no-more-unable-to-find-valid....

Right now i'm facing another problem. If I run my project fallowing the next steps, i can see the exchange.wsdl file
1. Right-click on your project and select “Run”
2. After deploying visit: http://localhost:8080/[Your Project Name]/exchange.wsdl

But if I run it fallowing the next steps, i can't see the exchange.wsdl file, and get some exceptions.
1. Using the “Projects” column on the left-hand side, find the package you created ExchangeDevelopmentTest in. Right-click on ExchangeDevelopmentTest.java and select “Run”.

Exception in thread "main" com.sun.xml.internal.ws.wsdl.parser.InaccessibleWSDLException: 2 counts of InaccessibleWSDLException.

java.io.FileNotFoundException: http://localhost:8080/ExchangeWebService/exchange.wsdl
java.io.FileNotFoundException: http://localhost:8080/ExchangeWebService/exchange.wsdl?wsdl

Any Ideas?

Accessing Exchange webservice 2007

Hi Reid,

I have a quick question, What i see is you are getting the WSDL and deploying in your
glassfish as http://localhost:8080/[Your Project Name]/exchange.wsdl".This way it will work.Am i missing some thing here , why are we
deplyoing the exchange.wsdl in glassfish and trying to access what you deployed.

I my case i have to hit the exchange Webservice directly and it does not work, i get an exception as "Exchange service is not valid" .

I saw the C# code which our .Net developer did it a giffy , they are calling as

ExchangeServiceBinding service = new ExchangeServiceBinding();

I would be happy to see if any one can through light so that i can see further....

thanks
Siva

Unsupported endpoint address

Hi Reid,

Thanks for the excellent article. I am running into this exception when I try to run the 'ExchangeDevelopmentTest' program. What could be the reason ? -

JAX-WS RI 2.1.3.1-hudson-417-SNAPSHOT: Stub for
Exception in thread "main" javax.xml.ws.WebServiceException: Unsupported endpoint address:
at com.sun.xml.ws.api.pipe.TransportTubeFactory.create(TransportTubeFactory.java:144)
at com.sun.xml.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:112)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595)

I am able to access the services.wsdl @ the mail server though.
Regards,
S.

Got over the "Unsupported Endpoint address" ......

.... by copy pasting the URL into the WSDL. But running into the :

Exception in thread "main" com.sun.xml.ws.client.ClientTransportException: request requires HTTP authentication: Unauthorized

.... and I have added the RetrieveWSDLAuthenticator lines too. Any ideas ? Also the same problem "Jan" mentions above wrt firefox/ie - i experience the very same.

Regards,
S.

Content type

Hi,

I get an error HTTP status code 415

content type 'text/xml;charset=utf-8' was not the expected type 'text/xml; charset=utf-8'

It looks like there is no easy workaround for this :-(

Can anybody help?

Thanks,
Anthony.

Hacking

Hacking /jax-ws-sources/jaxws-ri/rt/src/com/sun/xml/ws/transport/http/HttpAdapter.java from JAXWS 2.1 seems to work! Not a good solution though :-(

Add new comment