Archive for Java

maven compile jrxml to jasper

Unless your jasper reports change at runtime, .jrxml templates should be compiled at compile time into .jasper, and you will not need JDT at runtime, nor need to re-compile the reports each time it is run.

If you’re on maven, simply paste the usage guide into your pom and change your JasperCompileManager.compileReport(InputStream) into JRLoader.loadObject(InputStream).

Comments

When they say HashMap is not thread-safe, it means it is not.

We had this deadlock-like behavior where the UI froze sometimes when performing a particular action. But when run with our profiler, it did not report a deadlock when it froze.

After hours of tracing, the cause was identified as an infinite loop on the HashMap.get() method, running in the AWT Event Dispatch thread. The HashMap is the constraints object in a javax.swing.SpringLayout. Why would that happen???

More tracing revealed that there were multiple threads trying to add components to this container, triggering SpringLayout to add new constraints to its map. With reasonable luck the map hits its threshold and tries to resize itself. If you understand hashing you know that this is when it picks a new table size and re-hashes all the objects into its new buckets. When two of this happen at the same time the linked list screws up, and with more luck a later element in the link list points to the next element which is earlier in the same list. The worse part is this is a hidden problem, it doesn’t “surface” until you try to get() an object that’s even later than the later element, that’s when it iterates the bucket past the later element, back to the earlier element, and repeats.

The typical solution to swap the HashMap for a Hashtable is not available here, because the map exists in the core JDK. So it’s a good time to re-iterate to the team the significance of “single threaded model” of AWT/Swing. To be explicit, this issue was resolved by queuing the adding of components to the container on the Event Dispatch thread. Of course a more direct approach would be to synchronize the points where the components were added, but you shouldn’t be doing such things outside the AWT Event Dispatch thread anyway.

When I googled about the HashMap.get() infinite loop I realize it occurs in other areas as well, e.g. a Servlet’s session may be represented as a HashMap. Concurrent put()s and then a get() can cause the same problem.

Comments (6)

Reflecting outer class

Given an inner class object, how do you use reflection to obtain a reference to the outer class? this$0.


  Field parent = inner.getClass().getDeclaredField("this$0");
  parent.setAccessible(true);
  Object outer = parent.get(inner);

If it is a nested inner class, increment the 0.

Comments

Part II: Query Exchange availability with Java

Although very verbose, I’m just listing the minimum you need to run the query. If you use it you will likely need to use utility methods to modularize the code and alter the input.


ExchangeServices factory = new ExchangeServices();
ExchangeServicePortType service = factory.getExchangeServicePort();

// create request
GetUserAvailabilityRequestType request = 
    new GetUserAvailabilityRequestType();

// set timezone
SerializableTimeZoneTime standardTime = new SerializableTimeZoneTime();
standardTime.setTime("00:00:00");
standardTime.setDayOrder((short)1);
standardTime.setDayOfWeek(DayOfWeekType.SUNDAY);

SerializableTimeZone timezone = new SerializableTimeZone();
timezone.setBias(-8 * 60);	// CHANGE THIS TO YOUR TIMEZONE
timezone.setStandardTime(standardTime);
timezone.setDaylightTime(standardTime);
request.setTimeZone(timezone);

// set time window of meeting
try {
  DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
  Duration duration = new Duration();
  // CHANGE THESE DATES
  duration.setStartTime(datatypeFactory.newXMLGregorianCalendar(
    new GregorianCalendar(2009, Month.DECEMBER, 8, 7, 00)));
  duration.setEndTime(datatypeFactory.newXMLGregorianCalendar(
    new GregorianCalendar(2009, Month.DECEMBER, 8, 18, 00)));

  FreeBusyViewOptionsType options = new FreeBusyViewOptionsType();
  options.setTimeWindow(duration);
  options.getRequestedView().add("Detailed"); // retrieve subject info

  request.setFreeBusyViewOptions(options);
} catch (DatatypeConfigurationException e) {
  e.printStackTrace();
  System.exit(-1);
}

// set meeting rooms to check
EmailAddress emailAddress = new EmailAddress();
// CHANGE THIS TO YOUR ROOM
emailAddress.setAddress("MeetingRoom@my.exchange.com");

MailboxData mailbox = new MailboxData();
mailbox.setEmail(emailAddress);
mailbox.setAttendeeType(MeetingAttendeeType.REQUIRED);
ArrayOfMailboxData mailboxes = new ArrayOfMailboxData();
// ADD MULTIPLE ROOMS IF NEEDED
mailboxes.getMailboxData().add(mailbox);
request.setMailboxDataArray(mailboxes);

// create response
Holder<GetUserAvailabilityResponseType> responseHolder = 
    new Holder<GetUserAvailabilityResponseType>();

service.getUserAvailability(request, responseHolder);

List<FreeBusyResponseType> responses = 
    responseHolder.value.getFreeBusyResponseArray()
    .getFreeBusyResponse();

for (FreeBusyResponseType response: responses) {
  ArrayOfCalendarEvent events = 
    response.getFreeBusyView().getCalendarEventArray();
  if (events == null) continue;
  for (CalendarEvent event: events.getCalendarEvent()) {
    System.out.printf("%s - %s : %s\n", event.getStartTime(), 
      event.getEndTime(), event.getCalendarEventDetails().getSubject());
  }
}

This code will simply print out if there are conflicting events in the “time window” you specified for the given “rooms”. If you use people as the addresses you will be checking the availability of the people. If you don’t use “Detailed” you will just get the conflicting times. There will be one FreeBusyResponseType for each address you gave as input, in the same order. If there are no conflicts, events will be null.

See Part I for how to create the stubs, and Part III for the JFreeChart GUI.

Comments

Part I: Java -> MS Exchange Server

To assist my laziness I tried to write a utility that helps me check the available meeting rooms for booking faster than having to go to Outlook’s Calendar’s Scheduling Assistant.

Luckily, I found that my mail server has enabled Web Services, which should make my job much easier. The WSDL can be found at “https://my.exchange.com/EWS/exchange.asmx”. I tried to use Axis to generate the stubs, but hit an error.

{http://schemas.microsoft.com/exchange/services/2006/types}
ReminderMinutesBeforeStartType>null already exists

I searched and couldn’t find anything. Not wanting to dig into the implementation, I tried to switched to JAXWS. Not going well either.

At least one WSDL with at least one service definition needs to 
be provided.

This time I found the answer here. In fact I hit all the same problems as described even after solving this. I’ll repeat the solution here because I realize linking is good, but the sites might get torn down after some time.

Download the Services.wsdl, messages.xsd and types.xsd to your local disk. Edit Services.wsdl to add the service definition manually.

...
   <wsdl:service name="ExchangeServices">
     <wsdl:port name="ExchangeServicePort" binding="tns:ExchangeServiceBinding">
       <soap:address location="https://my.exchange.com/EWS/Exchange.asmx"/>
     </wsdl:port>
   </wsdl:service>
</wsdl:definitions>

With this added I generated the stubs. I used the “-Xnocompile” option to keep the .java files, so I copied them into Eclipse directly. This will be needed as we need to hack the source later.

I tried to call a simple API first – to resolve a name, or “Check Names”. How do I know what to call? Read the documentation.


ExchangeServices factory = new ExchangeServices();
ExchangeServicePortType service = factory.getExchangeServicePort();

// prepare request		
ResolveNamesType request = new ResolveNamesType();
request.setUnresolvedEntry("francis");

// prepare response
Holder<ResolveNamesResponseType> responseHolder = 
    new Holder<ResolveNamesResponseType>();

service.resolveNames(request, responseHolder);

ResolveNamesResponseMessageType response = 
    (ResolveNamesResponseMessageType) responseHolder.value.getResponseMessages()
    .getCreateItemResponseMessageOrDeleteItemResponseMessageOrGetItemResponseMessage()
    .get(0).getValue();
for (ResolutionType resolution: response.getResolutionSet().getResolution()) {
  System.out.printf("%s: %s", resolution.getMailbox().getName(), 
    resolution.getMailbox().getEmailAddress());
}

I hit the isNil problem also as described in the guide, so just comment out the fields that you are not using in ExchangeServicePortType such that you are left with the request and response.

This example is meant to demonstrate how to access Exchange with Java Web Services. If you use it you will likely need to handle errors, exceptions, nulls and the like.

Part II will show how to query the resource availability, and Part III shows how to display this results graphically using JFreeChart.

Comments (3)