Fork me on GitHub

n. Slang a rough lawless young Kuali developer.
[perhaps variant of Houlihan, Irish surname]
kualiganism n

Blog of an rSmart Java Developer. Full of code examples, solutions, best practices, et al.

Monday, June 6, 2011

Constants Done with Spring Part 2: Inheriting Constants

Motivation

In another chapter, I wrote about constants implemented through Spring. In one of my reasons for doing so, I illustrated that in Kuali, constraints are difficult to manipulate because of their static final nature. I called them an antipattern. Here's an example again:

Notice again that these constants cannot be manipulated. In the other chapter, I approached the use case that one would want to modify an existing constant and change it for their institution. In this chapter, I am going to approach the use case of adding a new constant. Why would you do this? Why not just make a new constants class, right? Well, you could do that. I find it to be more elegant to reuse your constants interface instead of having more than one.

The Pattern

Since we are using Spring, let's assume that we are using the aforementioned Spring constants implementation instead of the antipattern. Now that we know we are using Spring, there are a couple assumptions we can make.
  • Inversion of Control - we can assume that we can overwrite any known beans with the name we want to occupy. That is, if there is an existing constants implementation, we can not only reuse it, but replace it as well.
  • Dependency Injection - we can assume that we can inject any known constants we may already have into our new constants implementation.
  • We can reuse the existing KFS parentBean pattern.


With that, our methodology here is to first inject our existing constants into a new bean, then overwrite our old bean with it.

The Screencast




The Steps

1 Create a new Constants bean to be the delegate.

I created the following as my delegate.
<!--
Copyright 2007 The Kuali Foundation. Licensed under the Educational
Community License, Version 1.0 (the "License"); you may not use this
file except in compliance with the License. You may obtain a copy of
the License at http://www.opensource.org/licenses/ecl1.php Unless
required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing
permissions and limitations under the License.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<bean id="kimDelegateConstants" class="org.kuali.rice.kim.util.ConstantsImpl">
<property name="kimLdapIdProperty"         value="uaid" />
<property name="kimLdapNameProperty"       value="uid" />
<property name="snLdapProperty"            value="sn" />
<property name="givenNameLdapProperty"     value="givenName" />
<property name="entityIdKimProperty"       value="entityId" />
<property name="employeeMailLdapProperty"  value="mail" />
<property name="employeePhoneLdapProperty" value="employeePhone" />
<property name="defaultCountryCode"        value="1" />
<property name="mappedParameterName"       value="KIM_TO_LDAP_FIELD_MAPPINGS" />
<property name="mappedValuesName"          value="KIM_TO_LDAP_VALUE_MAPPINGS" />
<property name="parameterNamespaceCode"    value="KR-SYS" />
<property name="parameterDetailTypeCode"   value="Config" />
<property name="personEntityTypeCode"      value="PERSON" />
<property name="employeeIdProperty"        value="emplId" />
<property name="departmentLdapProperty"    value="employeePrimaryDept" />  
<property name="employeeTypeProperty"      value="employeeType" />
<property name="employeeStatusProperty"    value="employeeStatus" />
<property name="affiliationLdapProperty"   value="affiliationProperty" />
<property name="primaryAffiliationLdapProperty"   value="eduPersonPrimaryAffiliation" />
<property name="defaultCampusCode"         value="MC" />
<property name="defaultChartCode"          value="UA" />
<property name="taxExternalIdTypeCode"     value="TAX" />
<property name="externalIdProperty"        value="externalIdentifiers.externalId" />
<property name="externalIdTypeProperty"    value="externalIdentifiers.externalIdentifierTypeCode" />
<property name="affiliationMappings"       value="staff=STAFF,faculty=FCLTY,employee=STAFF,student=STDNT,affilate=AFLT"/>
<property name="employeeAffiliationCodes"  value="STAFF,FCLTY" />
</bean>
...
...
</beans>
The important thing to notice is that it's in a new bean and not kimConstants any longer.

2 Override the original kimConstants bean

Now you need to create a new kimConstants bean that uses your implementation and delegates to the delegate created in Step 1
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2007 The Kuali Foundation. Licensed under the Educational
Community License, Version 1.0 (the "License"); you may not use this
file except in compliance with the License. You may obtain a copy of
the License at http://www.opensource.org/licenses/ecl1.php Unless
required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing
permissions and limitations under the License.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
...
...
<bean id="kimConstants" class="edu.arizona.kim.util.ConstantsImpl">
<property name="phoneNumberMask"           value="###-###-####" />
<property name="delegate"                  value-ref="kimDelegateConstants" />
</bean>
</beans>
Here a new kimConstants is created. It only has 2 properties. One is for the delegate and the other is the field I wanted to add.

3. Create a new interface for your constants that includes your new field

/*
* Copyright 2007-2009 The Kuali Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ecl2.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.arizona.kim.util;


/**
* Extension interface for constants
*/
public interface Constants extends org.kuali.rice.kim.util.Constants {

/**
* Retrieve the phoneNumberMask constant
*
* @return String instance of the phoneNumberMask
*/
String getPhoneNumberMask();
}
You can see it extends the original constants interface and thereby gaining all its abstract methods for all the delegate method's properties.

4 Create the implementation class for the new bean

/*
* Copyright 2007-2009 The Kuali Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ecl2.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.arizona.kim.util;

import java.util.Collection;

import org.kuali.rice.kim.bo.entity.dto.KimEntityInfo;

/**
* Extension implementation for constants
*
*/
class ConstantsImpl implements Constants {
private String phoneNumberMask;
private org.kuali.rice.kim.util.Constants delegate;

public void setDelegate(final org.kuali.rice.kim.util.Constants delegate) {
this.delegate = delegate;
}

public org.kuali.rice.kim.util.Constants getDelegate() {
return delegate;
}

public Collection getTestPrincipalNames() {
return getDelegate().getTestPrincipalNames();
}


/**
* Gets the value of entityPrototype
*
* @return the value of entityPrototype
*/
public KimEntityInfo getEntityPrototype() {
return getDelegate().getEntityPrototype();
}

/**
* Gets the value of externalIdTypeProperty
*
* @return the value of externalIdTypeProperty
*/
public String getExternalIdTypeProperty() {
return getDelegate().getExternalIdTypeProperty();
}

/**
* Gets the value of taxExternalIdTypeCode
*
* @return the value of taxExternalIdTypeCode
*/
public String getTaxExternalIdTypeCode() {
return getDelegate().getTaxExternalIdTypeCode();
}


/**
* Gets the value of externalIdProperty
*
* @return the value of externalIdProperty
*/
public String getExternalIdProperty() {
return getDelegate().getExternalIdProperty();
}

/**
* Gets the value of employeePhoneLdapProperty
*
* @return the value of employeePhoneLdapProperty
*/
public String getEmployeePhoneLdapProperty() {
return getDelegate().getEmployeePhoneLdapProperty();
}

/**
* Gets the value of employeeMailLdapProperty
*
* @return the value of employeeMailLdapProperty
*/
public String getEmployeeMailLdapProperty() {
return getDelegate().getEmployeeMailLdapProperty();
}

/**
* Gets the value of defaultCountryCode
*
* @return the value of defaultCountryCode
*/
public String getDefaultCountryCode() {
return getDelegate().getDefaultCountryCode();
}

/**
* Gets the value of personEntityTypeCode
*
* @return the value of personEntityTypeCode
*/
public String getPersonEntityTypeCode() {
return getDelegate().getPersonEntityTypeCode();
}

/**
* Gets the value of kimLdapIdProperty
*
* @return the value of kimLdapIdProperty
*/
public String getKimLdapIdProperty() {
return getDelegate().getKimLdapIdProperty();
}

/**
* Gets the value of kimLdapNameProperty
*
* @return the value of kimLdapNameProperty
*/
public String getKimLdapNameProperty() {
return getDelegate().getKimLdapNameProperty();
}

/**
* Gets the value of snLdapProperty
*
* @return the value of snLdapProperty
*/
public String getSnLdapProperty() {
return getDelegate().getSnLdapProperty();
}

/**
* Gets the value of givenNameLdapProperty
*
* @return the value of givenNameLdapProperty
*/
public String getGivenNameLdapProperty() {
return getDelegate().getGivenNameLdapProperty();
}

/**
* Gets the value of entityIdKimProperty
*
* @return the value of entityIdKimProperty
*/
public String getEntityIdKimProperty() {
return getDelegate().getEntityIdKimProperty();
}

/**
* Gets the value of parameterNamespaceCode
*
* @return the value of parameterNamespaceCode
*/
public String getParameterNamespaceCode() {
return getDelegate().getParameterNamespaceCode();
}

/**
* Gets the value of parameterDetailTypeCode
*
* @return the value of parameterDetailTypeCode
*/
public String getParameterDetailTypeCode() {
return getDelegate().getParameterDetailTypeCode();
}

/**
* Gets the value of mappedParameterName
*
* @return the value of mappedParameterName
*/
public String getMappedParameterName() {
return getDelegate().getMappedParameterName();
}

/**
* Gets the value of unmappedParameterName
*
* @return the value of unmappedParameterName
*/
public String getUnmappedParameterName() {
return getDelegate().getUnmappedParameterName();
}

/**
* Gets the value of mappedValuesName
*
* @return the value of mappedValuesName
*/
public String getMappedValuesName() {
return getDelegate().getMappedValuesName();
}

/**
* Gets the value of employeeIdProperty
*
* @return the value of employeeIdProperty
*/
public String getEmployeeIdProperty() {
return getDelegate().getEmployeeIdProperty();
}

/**
* Gets the value of departmentLdapProperty
*
* @return the value of departmentLdapProperty
*/
public String getDepartmentLdapProperty() {
return getDelegate().getDepartmentLdapProperty();
}

/**
* Gets the value of employeeTypeProperty
*
* @return the value of employeeTypeProperty
*/
public String getEmployeeTypeProperty() {
return getDelegate().getEmployeeTypeProperty();
}

/**
* Gets the value of employeeStatusProperty
*
* @return the value of employeeStatusProperty
*/
public String getEmployeeStatusProperty() {
return getDelegate().getEmployeeStatusProperty();
}

/**
* Gets the value of defaultCampusCode
*
* @return the value of defaultCampusCode
*/
public String getDefaultCampusCode() {
return getDelegate().getDefaultCampusCode();
}

public String getDefaultChartCode() {
return getDelegate().getDefaultChartCode();
}

public String getEmployeeAffiliationCodes() {
return getDelegate().getEmployeeAffiliationCodes();
}
public String getAffiliationMappings() {
return getDelegate().getAffiliationMappings();
}

/**
* Gets the mappings for the affiliation ldap property
* @return mapping for KIM affiliation and LDAP
*/
public String getAffiliationLdapProperty() {
return getDelegate().getAffiliationLdapProperty();
}

/**
* Gets the mappings for the primary affiliation ldap property
* @return mapping for KIM primary affiliation and LDAP
*/
public String getPrimaryAffiliationLdapProperty() {
return getDelegate().getPrimaryAffiliationLdapProperty();
}

/**
* @see edu.arizona.kim.util.Constants#getPhoneNumberMask()
*/
public String getPhoneNumberMask() {
return this.phoneNumberMask;
}

/**
* Sets the phone number mask constant
*
* @param phoneNumberMask value to set for the phoneNumberMask constant
*/
public void setPhoneNumberMask(final String phoneNumberMask) {
this.phoneNumberMask = phoneNumberMask;
}
}
Notice the following allover the place
/**
* Gets the mappings for the primary affiliation ldap property
* @return mapping for KIM primary affiliation and LDAP
*/
public String getPrimaryAffiliationLdapProperty() {
return getDelegate().getPrimaryAffiliationLdapProperty();
}
The getDelegate() call is accessing the delegate we setup in spring. The dependency injection takes care of everything for us, so we don't need to worry about it being a package level class either. We also only override the getters because this is a constant. We're not supposed to change it.

Conclusion

There you have it. Another reason to use constants in spring. Not only are they easy to define, but now you can use object composition to inherit constants from other beans.

No comments:

Post a Comment