XSL: Convert timezone abbreviation to hours

Convert timezone abbreviation to hours

<hours><xsl:value-of select="local:getTimeZoneHours('CET')"/></hours>

will have as result

<hours>1</hours>

Here is the function code

<!-- Returns TimeZone in hours-->
 
    <xsl:function name="local:getTimeZoneHours">
        <xsl:param name="timezone" as="xs:string"/>
        <xsl:variable name="timezones">
            <timezones>
                <timezone>
                    <time>0</time>
                    <name>GMT</name>
                    <description>Greenwich Mean Time</description>
                </timezone>
                <timezone>
                    <time>0</time>
                    <name>UTC</name>
                    <description>Universal Coordinated Time </description>
                </timezone>
                <timezone>
                    <time>0</time>
                    <name>WET</name>
                    <description>Western European Time </description>
                </timezone>
                <timezone>
                    <time>-2</time>
                    <name>AT</name>
                    <description>Azores Time</description>
                </timezone>
                <timezone>
                    <time>-4</time>
                    <name>AST</name>
                    <description>Atlantic Standard Time</description>
                </timezone>
                <timezone>
                    <time>-5</time>
                    <name>EST</name>
                    <description>Eastern Standard Time </description>
                </timezone>
                <timezone>
                    <time>-6</time>
                    <name>CST</name>
                    <description>Central Standard Time </description>
                </timezone>
                <timezone>
                    <time>-7</time>
                    <name>MST</name>
                    <description>Mountain Standard Time </description>
                </timezone>
                <timezone>
                    <time>-8</time>
                    <name>PST</name>
                    <description>Pacific Standard Time</description>
                </timezone>
                <timezone>
                    <time>-9</time>
                    <name>YST</name>
                    <description>Yukon Standard Time</description>
                </timezone>
                <timezone>
                    <time>-10</time>
                    <name>AHST</name>
                    <description>Alaska-Hawaii Standard Time </description>
                </timezone>
                <timezone>
                    <time>-10</time>
                    <name>CAT</name>
                    <description>Central Alaska Time </description>
                </timezone>
                <timezone>
                    <time>-10</time>
                    <name>HST</name>
                    <description>Hawaii Standard Time </description>
                </timezone>
                <timezone>
                    <time>-11</time>
                    <name>NT</name>
                    <description>Nome Time </description>
                </timezone>
                <timezone>
                    <time>-12</time>
                    <name>IDLW</name>
                    <description>International Date Line West</description>
                </timezone>
                <timezone>
                    <time>1</time>
                    <name>CET</name>
                    <description>Central European Time </description>
                </timezone>
                <timezone>
                    <time>1</time>
                    <name>FWT</name>
                    <description>French Winter Time </description>
                </timezone>
                <timezone>
                    <time>1</time>
                    <name>MET</name>
                    <description>Middle European Time </description>
                </timezone>
                <timezone>
                    <time>1</time>
                    <name>MEWT</name>
                    <description>Middle European Winter Time </description>
                </timezone>
                <timezone>
                    <time>1</time>
                    <name>SWT</name>
                    <description>Swedish Winter Time </description>
                </timezone>
                <timezone>
                    <time>2</time>
                    <name>EET</name>
                    <description>Eastern European Time </description>
                </timezone>
                <timezone>
                    <time>3</time>
                    <name>BT</name>
                    <description>Baghdad Time </description>
                </timezone>
                <timezone>
                    <time>7</time>
                    <name>WAST</name>
                    <description>West Australien Time</description>
                </timezone>
                <timezone>
                    <time>8</time>
                    <name>CCT</name>
                    <description>China Coast Time  </description>
                </timezone>
                <timezone>
                    <time>9</time>
                    <name>JST</name>
                    <description>Japan Standard Time </description>
                </timezone>
                <timezone>
                    <time>10</time>
                    <name>EAST</name>
                    <description>East Australian Standard Time </description>
                </timezone>
                <timezone>
                    <time>10</time>
                    <name>GST</name>
                    <description>Guam Standard Time</description>
                </timezone>
                <timezone>
                    <time>12</time>
                    <name>IDLE</name>
                    <description>International Date Line East</description>
                </timezone>
                <timezone>
                    <time>12</time>
                    <name>NZST</name>
                    <description>New Zealand Standard Time </description>
                </timezone>
                <timezone>
                    <time>1</time>
                    <name>BST</name>
                    <description>British Summer Time </description>
                </timezone>
                <timezone>
                    <time>-3</time>
                    <name>ADT</name>
                    <description>Atlantic Daylight Time </description>
                </timezone>
                <timezone>
                    <time>-4</time>
                    <name>EDT</name>
                    <description>Eastern Daylight Time </description>
                </timezone>
                <timezone>
                    <time>-5</time>
                    <name>CDT</name>
                    <description>Central Daylight Time </description>
                </timezone>
                <timezone>
                    <time>-6</time>
                    <name>MDT</name>
                    <description>Mountain Daylight Time </description>
                </timezone>
                <timezone>
                    <time>-7</time>
                    <name>PDT</name>
                    <description>Pacific Daylight Time </description>
                </timezone>
                <timezone>
                    <time>-8</time>
                    <name>YDT</name>
                    <description>Yukon Daylight Time </description>
                </timezone>
                <timezone>
                    <time>-9</time>
                    <name>HDT</name>
                    <description>Hawaii Daylight Time </description>
                </timezone>
                <timezone>
                    <time>2</time>
                    <name>MEST</name>
                    <description>Middle European Summer Time</description>
                </timezone>
                <timezone>
                    <time>2</time>
                    <name>CEST</name>
                    <description>Central European Summer Time</description>
                </timezone>
                <timezone>
                    <time>2</time>
                    <name>SST</name>
                    <description>Swedish Summer Time </description>
                </timezone>
                <timezone>
                    <time>2</time>
                    <name>FST</name>
                    <description>French Summer Time</description>
                </timezone>
                <timezone>
                    <time>8</time>
                    <name>WADT</name>
                    <description>West Australian Daylight Time</description>
                </timezone>
                <timezone>
                    <time>11</time>
                    <name>EADT</name>
                    <description>East Australian Daylight Time </description>
                </timezone>
                <timezone>
                    <time>13</time>
                    <name>NZDT</name>
                    <description>New Zealand Daylight Time </description>
                </timezone>
            </timezones>
        </xsl:variable>
 
        <xsl:variable name="hours">
                    <xsl:value-of select="$timezones//timezone[name=upper-case($timezone)]/time"/>
        </xsl:variable>
 
        <xsl:value-of select="xs:integer($hours)"/>
    </xsl:function>

Hibernate: Force Hibernate to save provided Version field value.

So, you want so save change Version value of a persistent object, and save it to database, using Hibernate.

A scenario for this is when you use detached objects which are sent as XML or JSON. In this case, if you want to reattach the object to a session, (for example to save the changes made on client side) you will have to provide the value for Version field, to prevent changes of newer version of objects.

Hibernate does not use the provided version, for checking. It simply assumes that he has the correct version, and even if the user sets a different version before saving, it simply ignores it.

One way to avoid this, is to add a HibernateInterceptor, which intercepts the update requests (onFlushDirty)

public boolean onFlushDirty(Object entity, Serializable id,
			Object[] currentState, Object[] previousState,
			String[] propertyNames, Type[] types) {
 
	//if it is not BOInterface, just flush the object
	if(! (entity instanceof com.package.BOInterface))
		return super.onFlushDirty(entity, id, currentState, previousState,
				propertyNames, types);
	//get the version field index
	int vidx = 0;
	for (String name : propertyNames) {
		if(name.equalsIgnoreCase("version")) {
			break;
		}
		vidx++;
	}
 
	if( ((Integer)currentState[vidx]).intValue()==((Integer)previousState[vidx]).intValue() ) {
		return super.onFlushDirty(entity, id, currentState, previousState,
				propertyNames, types);		
	}
	logger.info("OnFlushDirty called. Concurrent modification");
 
	throw new ConcurrentModificationException(entity.getClass().getName()+" has a different version in the database.");
	}

I used an Interface to be sure that the BO has the Version field.

 
public interface BOInterface {
	public int getVersion();
}

 

To add the Interceptor to Hibernate using spring, all you have to do is to add a property to the session factory:

<bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="entityInterceptor">
			<bean class="com.package.HibernateSaveBOInterceptor"/>
		</property>
        <property name="dataSource" ref="dataSource" />
 
        <property name="packagesToScan" value="com.package"/>
 
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <!-- <prop key="hibernate.hbm2ddl.auto">update</prop> -->
            </props>
        </property>
    </bean>

SpringMVC REST with validation of input XML

To set up REST with springMVC, we need to add to the DispatcherServlet’s configuration file the following beans:
xmlMarshaller and marshallingHttpMessageConverter

The xmlMarshaller is used to convert java classes to XML and XML back to java classes.
We can use the jaxb-2.0.jar library, and define the xmlMarshaller in spring configuration file as:

    <oxm:jaxb2-marshaller id="xmlMarshaller">
       <oxm:class-to-be-bound name="com.Class1" />
       <oxm:class-to-be-bound name="com.Class2" />
    </oxm:jaxb2-marshaller>

in order to this work correctly we need to add the xmlns:oxm=”http://www.springframework.org/schema/oxm”
namespace with schema location
http://www.springframework.org/schema/oxm/spring-oxm-1.5.xsd

Also, we need to define a message converter to use the xmlMarshaller in spring configuration file:

    <bean id="marshallingHttpMessageConverter"
         class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
          <property name="marshaller" ref="xmlMarshaller" />
          <property name="unmarshaller" ref="xmlMarshaller" />
    </bean>

To be able to automatically convert a java object to xml in the response, we needs to bind the message converter to a MethodHandlerAdapter:

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
           <util:list id="beanList">
               <ref bean="marshallingHttpMessageConverter" />
           </util:list>
        </property>
    </bean>

With this configuration, any springMVC controller can have object tagged with @ResponseBody as return and tagged with @RequestBody in parameter list. Thanks to the message converters, the conversion of xml to java object and java object to xml is done automatically by spring.

@ResponseBody
    public Class1 login(@RequestBody Class2 request) {
           return new class1();
   }....

But what if we would like to have a validation of the input? Well, we have 2 solutions:

1. use the marshaller’s support for validation (jaxb permits definition of how an element is serialized/deserialized)
2. get the input xml and validate it at controller level, against an xsd.

In first case, we can add attributes to the @XmlElement annotation (like @XmlElement(nillable=true, required=true). More on this at http://jaxb.java.net/nonav/2.2.3/docs/api/javax/xml/bind/annotation/XmlElement.html .

In second case, we already have an xsd file, and we want to validate the @RequestBody against it. To do so, first we have to add the xmlMarshaller to the controller itself:

@Autowired()  
private Jaxb2Marshaller xmlMarshaller;

second, we have to change the signature of the method in controller. More exactly, we need a HttpServletRequest, to be able to get the @RequestBody’s xml , and validate it.

@Controller
public class LoginController {
 
public Class1 login(HttpServletRequest request, HttpServletResponse response){
       //Get the xml as string from the request
       Source source = new StreamSource(request.getInputStream());
       Transformer transformer = TransformerFactory.newInstance().newTransformer();
 
       StreamResult result = new StreamResult(new StringWriter());
       transformer.transform(source, result);
 
       String xmlString = result.getWriter().toString();
 
       // validate the xml
         ....
       // end validation
 
       //unmarshal the @RequestBody from the input XML
       source = new StreamSource(new StringReader(xmlString)); 
       Class2 req = (Class2) xmlMarshaller.unmarshal(source);
    } 
}

JSF: Primefaces editing rows from a datatable using dialog and AJAX

Primefaces can be used to create nice looking user interfaces. I’ll show you how to create a datatable, how to add data to it and how to edit the content of a row, using a dialog and ajax.

First, we need a backing bean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class AccountBean implements Serializable {
 
@EJB
private AccountSession accountSession;
 
private Account account = new Account();
 
public ListgetAccounts() {
 
return accountSession.retrieve();
}
 
public Account getDetails() {
return account;
}
 
public void setDetails(Account account) {
this.account = account;
}
 
public void newAccount() {
 
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
ViewHandler viewHandler = application.getViewHandler();
UIViewRoot viewRoot = viewHandler.createView(context, context.getViewRoot().getViewId());
context.setViewRoot(viewRoot);
context.renderResponse();
account = new Account();
 
}
 
public void saveAccount() {
RequestContext context = RequestContext.getCurrentInstance();
 
context.addCallbackParam("saved", "true");
accountSession.update(account);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
 
<h:form id="listForm">  
            <p:growl id="messages"/>
            <p:panel header="Accounts" >
                <p:dataTable widgetVar="dataTable" id="list" var="item" value="#{account.accounts}"                            
                             rowKey="#{item.id}" selection="#{account.details}" selectionMode="single"
                             >            
 
                     <p:ajax event="rowSelect"    
                            update=":editForm:dialogPanel :listForm:messages" oncomplete="accountDialog.show()" />                      
 
                    <p:column headerText="Id" footerText="Id" style="width:80px">                          
                        <h:outputText value="#{item.id}" />  
                    </p:column> 
 
                    <p:column headerText="Login" footerText="Login" style="width:80px">                          
                        <h:outputText value="#{item.login}" />  
                    </p:column>  
                    <p:column headerText="Email" footerText="Email" style="width:125px">  
                        <h:outputText value="#{item.email}" />  
                    </p:column>  
                    <f:facet name="footer">  
                        <p:commandButton value="Add"   icon="ui-icon-plus"
                                         action="#{account.newAccount}"  
                                         update=":editForm:dialogPanel :listForm:messages" oncomplete="accountDialog.show()"/>                                                           
                    </f:facet>
                </p:dataTable>                
            </p:panel>
        </h:form>
        <h:form id="editForm" prependId="false">            
            <p:dialog id="accountDialog"  header="Account Details" widgetVar="accountDialog" resizable="false" modal="true" >
                <p:outputPanel id="dialogPanel">
                    <h:panelGrid id="display" columns="2" cellpadding="4">                         
 
                        <h:outputText value="Login" rendered="#{empty account.details.id}" />  
                        <p:inputText id="login" value="#{account.details.login}" rendered="#{empty account.details.id}" />
 
                        <h:outputText value="Email" />  
                        <p:inputText value="#{account.details.email}" required="true"/>
 
                        <h:outputText value="Password" />  
                        <p:password id="password" value="#{account.details.password}" inline="true" required="true"/>
 
                    </h:panelGrid>
                </p:outputPanel>
                <f:facet name="footer">  
                    <p:commandButton value="Save"   icon="ui-icon-check" action="#{account.saveAccount}"                                          
                                     process="@form"
                                     update=":listForm:list :editForm:dialogPanel :listForm:messages " 
                                     oncomplete="handleSubmitRequest(xhr, status, args)"/> 
 
                    <p:commandButton value="Cancel"   icon="ui-icon-close" 
                                     action="#{account.newAccount}" 
                                     oncomplete="accountDialog.hide()" 
                                     process="@this"
                                     update=":listForm:list :editForm:dialogPanel :listForm:messages "
                                     />                                         
                </f:facet>
 
            </p:dialog>
            <!-- end dialog -->
        </h:form> 
        <script type="text/javascript">  
            function handleSubmitRequest(xhr, status, args) {  
                if(args.saved!='true') {  
                    jQuery('#accountDialog').effect("shake", { times:1 }, 50);   
                } else {                                      
                    accountDialog.hide();   
                }
            }  
        </script>
        <br/>

Some explanations of the code:

When a row in the datatable is selected, the edit dialog is automatically shown, using an ajax event:

 <p:ajax event="rowSelect" 
     update=":editForm:dialogPanel :listForm:messages" oncomplete="accountDialog.show()" />

updates the dialog content with the selected row’s data and shows the edit dialog when a row in the datatable is selected.

When the Add button is pressed, a new account instance is created in the backing bean, the dialog content is updated, and the dialog is shown. Since there is a new object to be added, we’ll render (or show) also the login related part.

On the edit dialog, we have 2 buttons, one for saving the form values, and the other to cancel the changes. Both of them are ajax enabled.

The main problem with ajax submit is that it does not make a full page refresh. When the dialog having invalid data is submitted, JSF framework validates the form and marks it as invalid, primefaces updates the user interface accordingly but, if we close the dialog and reopen it (lets say we pressed the add button, tried to save empty fields, closed the dialog and then selected an existing row from the table), the dialog will have the invalid fields highlighted.

To avoid that, when creating a new Account instance, we have to reset the validation status of the form, by creating a new View:

FacesContext context = FacesContext.getCurrentInstance();
        Application application = context.getApplication();
        ViewHandler viewHandler = application.getViewHandler();
        UIViewRoot viewRoot = viewHandler.createView(context, context.getViewRoot().getViewId());
        context.setViewRoot(viewRoot);
        context.renderResponse();

To reset the form field values, we create a new instance of Account, each time the form is closed – when the Cancel button is pressed – and we hide the form.

Happy coding :)