Tuesday, October 14, 2008

beanValidator Validates Pojo's Attributes Easily

It is powerful tool from spring, I guess it's only in spring because I never user the other framework such as tapestry or struts. It automatically validate application from filling fields of the pojos. And it is so simple because only add line above the attribute setters in its XDoclet, and small validator in validation-global.xml, and a line in action-servlet and application properties for the error message.

Ok, let's take a look in my pojo Lbuibp, which mean Reporter Bank, below is some code sniplet from it:


/**
* @spring.validator type="required" type="mask" msgkey="errors.char9"
* @spring.validator-var name="mask" value="${char9}"
*/
public void setId(String id) {
this.id = id;
}
/**
* @spring.validator type="mask" msgkey="errors.number8"
* @spring.validator-var name="mask" value="${number8}"
*/
public void setKursLaporan(Long kursLaporan) {
this.kursLaporan = kursLaporan;
}
/**
* @spring.validator type="required"
* @spring.validator type="mask" msgkey="errors.varchar30"
* @spring.validator-var name="mask" value="${varchar30}"
*/
public void setNamaBank(String namaBank) {
this.namaBank = namaBank;
}

Ok, those are setters of my attribute: id, kursLaporan, and namaBank, and their type is easily known which is char9, number8, and varchar30.

And then I add my own validator in validation-global.xml:
<constant>
<constant-name>char9</constant-name>
<constant-value>^[a-zA-Z0-9]{9}$</constant-value>
</constant>
<constant>
<constant-name>number8</constant-name>
<constant-value>^\d{1,8}$|^\d{1,2}((\,)?\d{3}){1,2}$</constant-value>
</constant>
<constant>
<constant-name>varchar30</constant-name>
<constant-value>^[\w\s.+*(),=:'"]{1,30}$</constant-value>
</constant>

- char9, it receives nine digits alphanumeric characters
- number8,
^\d{1,8}$ which receives number from 1 until 8 characters, or ^\d{1,2}((\,)?\d{3}){1,2}$ which receives 1 or 2 numbers, and then comma (or not), and then three numbers, comma and three number as a group, which is 1 or 2 of that group
- varchar30, it receives 1 or until 30 characters of set of word character, space, dot, plus, star, and etc characters.

And then in the action-servlet.xml we add a line in the lbuibpFormController bean which control the form of Lbuibp.
<bean id="lbuibpFormController" class="...webapp.action.LbuibpFormController">
...
<property name="validator"><ref bean="beanValidator"></ref>
...
</property>

And in the applicationResources.properties we add some message as below:

errors.char9={0} is invalid, it must 9 characters of string.
errors.number8={0} is invalid, it must 8 characters of number.
errors.varchar30={0} is invalid, it must maximum 30 characters of string.

And those error messages simply called if the user is inputing unreceivable syntax that will unpass of the beanValidator.

And this beanValidator is server side validation, we can add client side validation using javascript.

REGEX

Regex stands for Regular Expression, it also called re, I remember got it in automata or discrete math when bachelor. Basically, a regular expression is a pattern describing a certain amount of text. Their name comes from the mathematical theory on which they are based. Most of this post content is taken from http://www.regular-expressions.info, and I just copy and paste it.

Regex is a powerful tool when we already learn it, in my project, I used regex as field validator of my pojos and as validator of the uploaded file name, fyi, in my application there is a part that user upload files, and that file is filtered first by application, because my appliaction is monthly bank reporting, so it needs to know that the file is report in what month, I mean the file must named year and month in the last of its name.

11 Special Charactes
(metacharacters)
- the opening square bracket [
- the backslash \
- the caret ^
- the dollar sign $
- the period or dot .
- the vertical bar or pipe symbol |
- the question mark ?
- the asterisk or star *
- the plus sign +
- the opening round bracket (
- the closing round bracket )

If we want to use one of these metacharacters, we need to escape them with a backslash, or double backslash in java.

Non-Printable Characters
- \t to match a tab character (ASCII 0x09),
- \r
for carriage return (0x0D) , and
- \n for line feed (0x0A).
- More exotic non-printables are \a (bell, 0x07), \e (escape, 0x1B), \f (form feed, 0x0C) and \v (vertical tab, 0x0B).

And once again, we need double backslash in java, one backslash is for the regex commonly.

Regex Engine
A regular expression "engine" is a piece of software that can process regular expressions, trying to match the pattern to the given string.

There are two kinds of regex engines: text-directed engines, and regex-directed engines. Jeffrey Friedl calls them DFA and NFA engines, respectively.
http://www.regular-expressions.info is based on regex-directed engines, and that sites is based on pearl language. First, I thought java is also regex-directed, but surprisingly is not, I create mini program as told by the site to find out is java text-directed engines or regex-directed, and surprisingly it's text-directed. The regex is: regex|regex not and the string is regex not, Below is the code, If the resulting match is only regex, the engine is regex-directed. If the result is regex not, then it is text-directed. Below is the code, and the output is "Found 'regex not' at position 0":

public static void main(String[] args) {
Pattern p = Pattern.compile ( "regex|regex not", Pattern.CASE_INSENSITIVE ) ;
String text = "regex not";
Matcher m = p.matcher ( text ) ;
if ( m.matches() ) {
System.out.println ( "Found '" + m.group ( 0 ) + "' at position " + m.start ( 0 ) ) ;
}
else {
System.err.println("No found match");
}
}


Regex-directed always returns the leftmost match, if we applying regex cat to He captured a catfish for his cat, the engine will try to match the first token in the regex c to the first character in the match H. This fails. There are no other possible permutations of this regex, because it merely consists of a sequence of literal characters. So the regex engine tries to match the c with the e. This fails too, as does matching the c with the space. Arriving at the 4th character in the match, c matches c. The engine will then try to match the second token a to the 5th character, a. This succeeds too. But then, t fails to match p. At that point, the engine knows the regex cannot be matched starting at the 4th character in the match. So it will continue with the 5th: a. Again, c fails to match here and the engine carries on. At the 15th character in the match, c again matches c. The engine then proceeds to attempt to match the remainder of the regex at character 15 and finds that a matches a and t matches t.

The entire regular expression could be matched starting at character 15. The engine is "eager" to report a match. It will therefore report the first three letters of catfish as a valid match. The engine never proceeds beyond this point to see if there are any "better" matches.


But in java which is text
-directed, he report no match for that situation, I already try regex cat to He captured a catfish for his cat, and it report no match found, it only receive String cat.

Character Set or Character Class "[ ]"
With character set we can tell the regex engine to match only one out of several characters. Simply place the characters you want to match between square brackets. We can use a hyphen inside a character class to specify a range of characters. [0-9] matches a single digit between 0 and 9.


- \d is short for [0-9]
- \w stands for "word character", usually [A-Za-z0-9_]. Notice the inclusion of the underscore and digits.
- \s stands for "whitespace character".
- The negated versions, \D is the same as [^\d], \W is short for [^\w] and \S is the equivalent of [^\s].

Be careful when using the negated shorthands inside square brackets. [\D\S] is not the same as [^\d\s]. The latter will match any character that is not a digit or whitespace. So it will match x, but not 8. The former, however, will match any character that is either not a digit, or is not whitespace. Because a digit is not whitespace, and whitespace is not a digit, [\D\S] will match any character, digit, whitespace or otherwise.

If we repeat a character class by using the ?, * or + operators, we will repeat the entire character class, and not just the character that it matched. The regex [0-9]+ can match 837 as well as 222. But If we want to repeat the matched character, rather than the class, you will need to use backreferences. ([0-9])\1+ will match 222 but not 837.


Negated Character Classes
Typing a caret after the opening square bracket will negate the character class. The result is that the character class will match any character that is not in the character class. It is important to remember that a negated character class still must match a character. q[^u] does not mean: "a q not followed by a u". It means: "a q followed by a character that is not a u". It will not match the q in the string Iraq. It will match the q and the space after the q in Iraq is a country. Indeed: the space will be part of the overall match, because it is the "character that is not a u" that is matched by the negated character class in the above regexp.

Metacharacters Inside Character Classes
Note that the only special characters or metacharacters inside a character class are the closing bracket (]), the backslash (\), the caret (^) and the hyphen (-). The usual metacharacters are normal characters inside a character class, and do not need to be escaped by a backslash. To search for a star or plus, use [+*]. Your regex will work fine if you escape the regular metacharacters inside a character class, but doing so significantly reduces readability.

To include a backslash as a character without any special meaning inside a character class, you have to escape it with another backslash. [\\x] matches a backslash or an x. The closing bracket (]), the caret (^) and the hyphen (-) can be included by escaping them with a backslash, or by placing them in a position where they do not take on their special meaning. I recommend the latter method, since it improves readability. To include a caret, place it anywhere except right after the opening bracket. [x^] matches an x or a caret. You can put the closing bracket right after the opening bracket, or the negating caret. []x][^]x] matches any character that is not a closing bracket or an x. The hyphen can be included right after the opening bracket, or right before the closing bracket, or right after the negating caret. Both [-x] and [x-] match an x or a hyphen. matches a closing bracket or an x.

The Dot Matches (Almost) Any Character
The dot matches a single character, without caring what that character is. The only exception are newline characters. So by default, the dot is short for
the [^\n].

Anchors
Anchors are a different breed. They do not match any character at all. Instead, they match a position before, after or between characters. And they are Zero-Length Matches.
- The caret ^ matches the position before the first character in the string.
- $ matches right after the last character in the string.
- \b matches at a position that is called a "word boundary"


Applying ^a to abc matches a. ^b will not match abc at all, because the b cannot be matched right after the start of the string, matched by ^. While c$ matches c in abc, while a$ does not match at all.

There are four different positions that qualify as word boundaries:
* Before the first character in the string, if the first character is a \w.
* After the last character in the string, if the last character is a
\w.
* Between a
\w and a non-word character following right after \w.
* Between a \W and a
\w following right after \W character.

In the regex-engine,
\bis\b will match This island is beautiful. Space is non word character, and the others are. The engine has successfully matched the word is in our string, skipping the two earlier occurrences of the characters i and s. If we had used the regular expression is, it would have matched the is in This.

Alternation "|"
The alternation operator has the lowest precedence of all regex operators. That is, it tells the regex engine to match either everything to the left of the vertical bar, or everything to the right of the vertical bar. If we want to limit the reach of the alternation, we will need to use round brackets for grouping.

Optional "?"
It is greedy. The question mark gives the regex engine two choices: try to match the part the question mark applies to, or do not try to match it. The engine will always try to match that part. Only if this causes the entire regular expression to fail, will the engine try ignoring the part the question mark applies to.

The effect is that if you apply the regex Feb 23(rd)? to the string Feb 23rd, the match will always be Feb 23rd and not Feb 23. You can make the question mark lazy (i.e. turn off the greediness) by putting a second question mark after the first.

"?,*, +,{}"
- ? is optional, 1 or 0
- * is 0 or more repetition
- + is 1 or more repetition
- {} is limiting repetition, The syntax is {min,max}
, if we want exactly n reeptition so the syntax is {n}

Again, they are greedy, suppose we want to receive html tag with this regex:
<.+>. when we test it on a string like This is a first test. we might expect the regex to match and when continuing after that match, . But it does not. The regex will match first. Obviously not what we wanted. The reason is that the plus is greedy. That is, the plus causes the regex engine to repeat the preceding token as often as possible. Only if that causes the entire regex to fail, will the regex engine backtrack. That is, it will go back to the plus, make it give up the last iteration, and proceed with the remainder of the regex.

To fix the problem:
- laziness, by adding "?", so the regex will becomes <.+?>.

- better solution without backtracking: We can use a greedy plus and a negated character class: <[^>]+>.

Grouping and Backreference "()"
Besides grouping part of a regular expression together, round brackets also create a "backreference". A backreference stores the part of the string matched by the part of the regular expression inside the parentheses.

([a-c])x\1x\1 will match axaxa, bxbxb and cxcxc. \1 is calling backreference ([a-c]). and in java we need double backslash rather than single backslash.

The other example is <([A-Z][A-Z0-9]*)\b[^>]*>.*? that want to match a pair of opening and closing HTML tags, and the text in between, such text bold italic.


Java also support forward reference, that is: we can use a backreference to a group that appears later in the regex. Obviously only useful if they're inside a repeated group. The example is (\2two|(one))+ will match oneonetwo.

Wednesday, September 24, 2008

XDoclet Serial Type Mapping

I was in mistake, I did the wrong way to get the id in a table which is Long and always increment in oracle
such as from table APP_USER.

Wrong Way I:
- I create sequence in the schema, for example for APP_USER:
CREATE SEQUENCE "SCHEMANAME"."SEQ_APP_USER_ID" MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 30 NOORDER NOCYCLE ;

- I create trigger before insert, in which it will increment if the ID is null
create or replace TRIGGER BI_APP_USER
before insert on APP_USER
for each row
begin
if :new.id is null
then select SEQ_APP_USER_ID.nextval into :NEW.ID from dual;
end if;
end;

- And in the pojo, the getter of the ID, is like this:
/**
* @return Returns the id.
* @hibernate.id column="ID" unsaved-value="null"
* @hibernate.generator class="increment"
*/
public Long getId() {
return id;
}

and belive it or not I got this way from browse the net, sadly I didn't save the address, it's from such a forum I think.

I did this method for some of my pojos, and few of them didn't work, I don't know why, in case it need tobe fixed fast, so I use another way,

Wrong Way II:
- Simply it check the maximum value of the id, and then I increment it before insert.
- I add method to get the maximum id of the table, in the DaoHibernate seems like this
@Override
public Long getMaxId() {
Long maxId = (Long) getSession().createQuery("select max(id) from LogTable ").uniqueResult();
return maxId;
}
- And offcourse the insert code just like below:
public void saveLogTable(final LogTable logTable) {
if (logTable.getId() == null) logTable.setId(getMaxId() + 1);
getHibernateTemplate().saveOrUpdate(logTable);
getHibernateTemplate().flush();
}
- And the getter of the pojo is like this:
/**
* @return Returns the id.
* @hibernate.id column="ID"
* @hibernate.generator class="assigned"
*/
public Long getId() {
return id;
}

- It doesn't need to create sequencial, but offcourse it consume resource because it count the record first.

Thanks for fellow in front of mine, that give me information how to do it right for getting the id before inserting:

The Right Way is over here:
- It only need to create the sequence same as the first way
- The pojo looks like this:
/**
* @hibernate.id column="ID" not-null="true" unique="true" type="long"
* @hibernate.generator class="sequence"
* @hibernate.param name="sequence" value="SEQ_APP_USER_ID"
*/
public Long getId() {
return id;
}

just that, and it's very simple way!!

Tuesday, June 3, 2008

Hot-Deploy Makes Appfuse Cooler

Each time I change my .jsp or .java file, I must ant deploy to see the change in my application, it needs times, and after ant doing his job, tomcat also processing some bla bla things until it finished so I can open my web, it so consuming times, eventhough I only change my variable letter for example, and sometimes if tomcat not finished his bla bla things and I already open my app, it result me Perm gen error, I must kill -9 it from my terminal.

I was given by fellow to create hot-deploy and hot-deply-web-only, the last is if I only change my .jsp files, magically I donot need deploy anything if I modify the controller, just voila... it updated automatically. The first is if the last not worked, and if those still didn't work, I used the old deploy from appfuse. Here's the snipplet added in build.xml:


description="unwar into the servlet container's deployment directory">




description="unwar into the servlet container's deployment directory">

add this one line sintax in properties.xml:



Create new xml file, name it projectName.xml and write the following code (for example):
< context docbase="/home/wks-243/workspace/.../exploded/projectName" path="/projectName" >

&lt Context docBase="/home/wks-348/workspace/sigmalbu/exploded/sigmalbu" path="sigmalbu" /&gt


<context docbase="/home/wks-243/workspace/.../exploded/projectName" path="/projectName">
put it in $CATALINA_HOME/conf/Catalina/localhost/ directory

Shutdown your tomcat, and then ant hot-deploy, and then ant hot-deploy-web-only, and then start your server in debugging mode from your eclipse, and hope everything's fine.

Ok, afaik, the role is to copying everything the compile result into the exploded directory, so we donot need to compile manually if there is a change, it already compile and exist in exploded directory, unless we change our .jsp file, so we need to hot-deploy-web-only.

Monday, May 19, 2008

Let's Go Lazy

It needs a minuite to load Financials.htm, and needs more minuites to load EditFinancial.htm, sometimes permGem error, and the dumb thing is I thought it just perhaps the database server is backuping or doing something which make it slow. And the dumberer thing is I try to use other database server, I create the tables I need one by one, and then I load those data. And the dumbest thing is I feel my application is going faster with the new database although I can write email, download something, or perhaps watching Thomas Cup while waiting my form's load. It's more than Dumb and Dumberer the movies. It was Dumb, Dumberer, and Dumbest.

The Financial table only need CURRENCY_KEY, LOCATION_KEY, etc.. it doesn't need to have the DimCurrency, DimLocation, etc whole as an object to have my Financial object, so I donot need to write extra lazy="false" in my Pojo's XDoclet. It was my bad habit to copy=paste everything without comparing my needs, I copy the Xdoclet declaration from other source that turn not to be lazy one. Hibernate is automatically set to be lazy by default. here's taken from my DimCurrency:

/**
* @return Returns the financials.
*
* @hibernate.bag name="financials" lazy="true" cascade="all"
* @hibernate.collection-key column="CURRENCY_KEY"
* @hibernate.collection-one-to-many class="id.co.model.Financial"
*/
public List getFinancials() {
return financials;
}
public void setFinancials(List financials) {
this.financials = financials;
}

It's still gimme error after I set lazy, the something named GGG error or something. I browse the net and it says that it needs an empty constructor for the pojos, wheter the Financial or the Dims, I forgot it, I just add it into all my pojos. sorry I missed the link, I write this post after repair my application, set it to lazy, and everything's go faster after the lazy things. just let's go to be l[cr]azy for a while!

Friday, May 16, 2008

Updating Composite-id Object

Before continuing, I use appfuse-spring-hibernate, FYI. Ok, I already had Financial object with composite keys that I generate directly from my Pojo, now I get error if I update a record of it.

It's just said that it failed to convert from String to FinancialPk. And when I debug it, in FinancialFormController, it never enter the onSubmit method, there's same error when in processFormSubmission method.

This error is happened for two days, I already browse the net, asked some people, but still don't get the answer, so I encourage myself to ask to JUG, thank's I've got little and expensive clue:
PropertyEditor, so here's the steps, because it make me easier when I wrote it in walktrough style :
  • I need bind the id type in initBinder method in FInancialFormController, that error says that system cannot convert String to FinancialPk type. So I add it together with Date type and numbers type.
  • Before that I need to override the getAsText and setAsText, methods from PropertyEditor.
  • First I made FinancialPk implements PropertyEditor and add those methods, and I wrote in initBinder: binder.registerCustomEditor(FinancialPk.class, new FinancialPk()); but it results an error.
  • So, I browse the net and I need new class called FinancialPkSupport that extends PropertyEditorSupport which is an adapter of PropertyEditor interface, make a constructor that have one parameter: Class pkClass. And ofcourse, override those to methods.
  • And then in inintBinder in FinancialFormController I add this line: binder.registerCustomEditor(FinancialPk.class, new FinancialPkSupport(FinancialPk.class));
Here's my FinancialPkSupport:

public class FinancialPkSupport extends PropertyEditorSupport {
private Class pkClass;

public FinancialPkSupport() {}
public FinancialPkSupport(Class pkClass) {
this.pkClass = pkClass;
}

public String getAsText() {
Object value = getValue();
return value == null ? "" : ((FinancialPk) value).dimChartaccount.getAccountKey() + "," +
((FinancialPk) value).dimCurrency.getCurrencyKey() + "," +
((FinancialPk) value).dimLocation.getLocationKey() + "," +
((FinancialPk) value).dimTime.getDimensionKey();
}

public void setAsText(String string) throws IllegalArgumentException {
FinancialPk f = new FinancialPk();
StringTokenizer token = new StringTokenizer(string);
f.setDimChartaccount(new DimChartaccount(Long.valueOf(token.nextToken(","))));
f.setDimCurrency(new DimCurrency(token.nextToken(",")));
f.setDimLocation(new DimLocation(token.nextToken(",")));
f.setDimTime(new DimTime(Long.valueOf(token.nextToken(","))));
if (f == null) {
throw new IllegalArgumentException("FinancialPk is null: " + string);
}
setValue(f);
}
}

And here's my initBinder:
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
binder.registerCustomEditor(FinancialPk.class, new FinancialPkSupport(FinancialPk.class));

SimpleDateFormat specFormat = new SimpleDateFormat(Constants.DATE_FORMAT);
binder.registerCustomEditor(Date.class, new CustomDateEditor(specFormat,true));

NumberFormat nf = NumberFormat.getNumberInstance(request.getLocale());
nf.setMaximumFractionDigits(Integer.parseInt(Constants.MAX_FRAX_DIGITS));
binder.registerCustomEditor(Double.class, null,new CustomNumberEditor(Double.class, nf, true));
binder.registerCustomEditor(Long.class, null,new CustomNumberEditor(Long.class, true));
}

And good bye frustating error!!

Tuesday, May 13, 2008

Generate hibernate composite-id using XDoclet

Few tables don't allowed to have a serial id just as modern table as in the appfuse by default. Ok, I mention one table of it: Financial, it has four PKs which are FK from four different tables: DimChartaccount, DimCurrency, DimLocation, and DimTime.

I've search the net and knew that it called composite-id (multiples id), and browse again to find how to generate its hbm directly from my pojo and got one link : Franklin Garcia's blog, it shows how to do it, but I've try it but unfortunately it fails to generate as I need, it cannot generate the composite-id part, but now I already fix it. here's how to do it, hope it helps:
  • name it still as id, but the type not as integer anymore, and no need generator class="increment", its type is PkFinancial. It's name must id because Ive try to name it with pkFinancial but I've got error fails in setter when I deploy it
  • PkFinancial is your own class, it must implements Serializable, and the properties are all of the PKs
/**
* @hibernate.class table="FINANCIAL"
*/
public class Financial extends BaseObject {
PkFinancial id; //must id, cannot name it as pkFinancial
Double saldoRupiah;
/**
* @hibernate.id name="id" class="jesperBlog.PkFinancial" //need to mention it's class
*/
public PkFinancial getId() {
return id;
}
public void setId(PkFinancial id) {
this.id = id;
}
/**
* @hibernate.property column="SALDO_RUPIAH" type="double" //usual property
*/
public Double getSaldoRupiah() {
return saldoRupiah;
}
public void setSaldoRupiah(Double saldoRupiah) {
this.saldoRupiah = saldoRupiah;
}
}

public class PkFinancial extends BaseObject { //must implements Serializable, BaseObject already done it
DimTime dimTime;
DimLocation dimLocation;
DimChartaccount dimChartaccount;
DimCurrency dimCurrency;

/**
* @hibernate.many-to-one name="dimTime"//just usual property, in my case it's many-to-one
* column="TIME_KEY" class="jesperBlog.DimTime"
*/
public DimTime getDimTime() {
return dimTime;
}
public void setDimTime(DimTime dimTime) {
this.dimTime = dimTime;
}
/**
* @hibernate.many-to-one name="dimLocation" column="LOCATION_KEY" class="jesperBlog.DimLocation"
*/
public DimLocation getDimLocation() {
return dimLocation;
}
public void setDimLocation(DimLocation dimLocation) {
this.dimLocation = dimLocation;
}
//oter getters setters
}

And the generated hbm looks like this:
...
<hibernate-mapping>
<class name="jesperBlog.Financial" table="FINANCIAL">

<composite-id name="id" class="jesperBlog.PkFinancial">
<key-many-to-one name="dimTime" class="jesperBlog.DimTime" column="TIME_KEY"/>
<key-many-to-one name="dimLocation" class="jesperBlog.DimLocation" column="LOCATION_KEY"/>
<key-many-to-one name="dimChartaccount" class="jesperBlog.DimChartaccount" column="ACCOUNT_KEY"/>
<key-many-to-one name="dimCurrency" class="jesperBlog.DimCurrency" column="CURRENCY_KEY"/>
</composite-id>

<property name="saldoRupiah" type="double" column="SALDO_RUPIAH"/>
...
</class>
</hibernate-mapping>