Java – Funny stuffs with “java.net.MalformedURLException: unknown protocol: d”

I just got this crazy problem while deploying company‘s product in QC environment yesterday. We need to parse the server.xml file in order to configure the https port of Tomcat during run time. Have no idea why it could run on my machine, but could not run on some other servers. Searching around and find this. Creating file object solves the problem perfectly

DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(new File(filePath)); // instead of docBuilder.parse(filePath);

Xml Node Creation With Java

Sometimes, I have to work with xml file and create the xml node. The official way to deal with this is so awful because it requires me to write a lot of code. Therefore, I prefer this shortcut:

String xmlNode = "<Connector SSLEnabled=\"true\" clientAuth=\"false\" " + "keystoreFile=\"" + path + "\" " + "keystorePass=\"" + password
+ "\" keystoreType=\"PKCS12\" " + "maxThreads=\"150\" port=\"" + httpsPort + "\" protocol=\"HTTP/1.1\" "
+ "scheme=\"https\" secure=\"true\" sslProtocol=\"TLS\"/>";

Element node = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(xmlNode.getBytes()))
.getDocumentElement();

The above code is about trying to configure the server.xml of Tomcat during ant build process

Using Liquibase

My current Java project requires generating a database during run time (after deploying to the Web server). This could be done in several ways like using ant task, or even parsing the SQL script into each statement and run the Java code. However, maybe the optimal solution for this is using Liquibase. Here are some examples about Liquibase:
1. First, you need to have a changlog file. This is just a xml file containing all the xml statement to create the table

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog 
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog 
    http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<changeSet author="bubuzzz" id="1330078925314-2">
        <createTable tableName=”testing">
            <column name="TESTING_ID" type="VARCHAR(40)">
                <constraints nullable="false" primaryKey="true"/>
            </column>
            <column name="TESTING_DESCRIPTION" type="VARCHAR(1000)">
                <constraints nullable="false"/>
            </column>
        </createTable>
        <modifySql dbms="mysql"><append value=" engine innodb charset=utf8"/>
        </modifySql>
</changeSet>
</ databaseChangeLog>

The modifySql used when you want to add more details with a particular database. In my case, I want to add “enginer innodb, charset=utf8” when using Mysql
2. Checking whether your changelog is correct or not. Put your changlog into liquibase folder. Create a database called liquibaseDemo and then, open your favorite terminal emulator and go to your liquibase directory, run this command

liquibase --driver=com.mysql.jdbc.Driver --classpath=/home/bubuzzz/Projects/web/liquiDemo/WebRoot/WEB-INF/lib/mysql-connector-java-5.1.6-bin.jar --changeLogFile=changelog.xml --url="jdbc:mysql://localhost/liquibaseDemo" --username=root --password=123456 migrate

The above command explains itself already, rite? 🙂
3. If everything run well, you will have all the tables inside liquibaseDemo database
4. Finally, using Java code to call your changelog. This is the way to do it

 public boolean createDatabase(String dbName) {
		
	logger.debug("Database creating processing");
	Connection conn = null;
	try {
	    conn = getConnection(); // Create a normal JDBC connection 
	    Statement st = conn.createStatement();
	    st.executeUpdate("CREATE DATABASE " + dbName + ";");
	    return true;
	} catch (SQLException s) {
	    logger.error(s.toString());
	} catch (Exception e) {
	    logger.error(e.toString());
	}

	return false;
}
	
public boolean createTables(String dbName) {

    String changelog = "changelog.xml";
    Connection conn = null;
    
    try {			
        conn = getConnection();
        conn.setCatalog(dbName);		
        
        Database database =
                DatabaseFactory.getInstance().
                findCorrectDatabaseImplementation(new JdbcConnection(conn));
        
        Liquibase liObj = new Liquibase(changelog, 
             new FileSystemResourceAccessor(), database);
        liObj.update(null);
    
        return true;
    } catch (LiquibaseException e) {
        logger.error(e.toString());
    } catch (SQLException e) {
        logger.error(e.toString());
    } catch (ClassNotFoundException e) {
        logger.error(e.toString());
    }
    
    return false;
    
}

Custom validation in play framework

Writing custom validation in play framework is easy. For example, we have a form containing a checkbox to ask user whether he / she agrees with the terms of agreement during the registraion. So, in the View template, you can put like this

#{ifErrors}
<ul class="error">
	#{errors}
   	<li >${error} </li>
   	#{/errors}
</ul>
#{/ifErrors}


....

#{field 'agreeTerm' }
	<label>Agree with <a href="#">Term of use </a> ? </label>
	<input type="checkbox" id="${field.name}" name="${field.name}" />
	<br/>
#{/field} 

<input type="submit" id="submit" value="Continue">
<br/>

Everytime user presses submit button, data will be sent to the save function of User controller. So, we can make the validation here (it is ok if we put the validation in the model as well)

public class User extends Controller {
	public static void save(
		......
		@CheckWith(CheckingAgreed.class)
		boolean agreeTerm) {
	
		......	
	
	}
}

Now, we gonna put the CheckingAgreed class into the User controller. In the end, we will get something like this


import play.data.validation.Check;

public class User extends Controller {
	public static void save(
		......
		@CheckWith(CheckingAgreed.class)
		boolean agreeTerm) {
	
		......	
	
	}
	
	static class CheckingAgreed extends Check {
		@Override
		public boolean isSatisfied(Object User, 
			Object agreeTerm) {
			setMessage("You have to agree with the terms");
			return ((Boolean) agreeTerm).booleanValue() == true;  
		}
	}
}

Now if user does not check the checkbox, a error message “You have to agree with the terms” will appear. Messages can be also retrieved from properties files

Ajax Validation With Play Framework

Supposed you have a form and you need to validate it with jquery along with Play framework. So, this is the way to deal with it. Play framework has a template tag (jsAction) which will render a javascript function during run-time. This function, basically, will parse the action and some parameters into a real url so template can send back the data to the controller. I do not find it so handy for ajax process, but since it is plugged into the framework, so we just go with it.

1. Create a User model with several properties:  ‘username’, ‘password’, ‘firstname’, ‘lastname’, ‘gender’, ‘lGender’, ’email’, ‘dob’,’country’, ‘agreeTerm’

2. Create a template with a form to save data

#{form @save(), id:'registerFrm' }

<ul class="error"></ul>

#{field 'username' }
<label>Username</label>
<input type="text" id="${field.name}" name="${field.name}" />
<br/>
#{/field}

#{field 'password' }
<label>Password</label>
<input type="text" id="${field.name}" name="${field.name}" />
<br/>
#{/field}

#{field 'firstname' }
<label>First name</label>
<input type="text" id="${field.name}" name="${field.name}" />
<br/>
#{/field}

#{field 'lastname' }
<label>Last name</label>
<input type="text" id="${field.name}" name="${field.name}" />
<br/>
#{/field}

#{field 'gender' }
<label>I am a </label>
<input type="radio" value="male" name="${field.name}" checked="checked"/> <label> Male </label>
<input type="radio" value="female" name="${field.name}" /> <label> Female </label>
<br/>
#{/field}

#{field 'lGender' }
<label>Looking for a</label>
<input type="radio" value="male" name="${field.name}" /> <label> Male </label>
<input type="radio" value="female" name="${field.name}" checked="checked"/> <label> Female </label>
<br/>
#{/field}

#{field 'email' }
<label>Email</label>
<input type="text" id="${field.name}" name="${field.name}" />
<br/>
#{/field}

#{field 'dob' }
<label>Date of Birth</label>
<input type="text" id="${field.name}" name="${field.name}" />
<br/>
#{/field}

#{field 'country' }
<label>Country</label>
<input type="text" id="${field.name}" name="${field.name}" />
<br/>
#{/field}

#{field 'agreeTerm' }
<label>Agree with <a href="#">Term of use </a> ? </label>
<input type="checkbox" id="${field.name}" name="${field.name}" />
<br/>
#{/field}

<label> </label>
<input type="submit" id="submit" value="Continue">
<br/>

#{/form}

3. Dont forget to add “set ‘moreScripts’” tag at the beginning of the template


#{set 'moreScripts'}

....Magic jquery code goes here....

#{/set}

4. Put these code inside the set tag above

<script type="text/javascript">

    var listAction = #{jsAction @User.save(
                        ':username',
                        ':password',
                        ':firstname',
                        ':lastname',
                        ':gender',
                        ':lGender',
                        ':email',
                        ':dob',
                        ':country',
                        ':agreeTerm'
                    ) /};

    $(document).ready(function() {

        $('#submit').click (function(event) {

            event.preventDefault();
            $.post (listAction({
                username: $('#username').val(),
                password: $('#password').val(),
                firstname: $('#firstname').val(),
                lastname: $('#lastname').val(),
                gender: $('#gender').val(),
                lGender: $('#lGender').val(),
                email: $('#email').val(),
                dob: $('#dob').val(),
                country: $('#country').val(),
                agreeTerm: $('#agreeTerm').val(),
                }), function(data){
                    $('.error').html(data);
            });

        });

    });

</script>

Ok, too many magic lines,rite? What the hell is listAction variable doing here ? Here is the thing: you open your browser, go to the url which will render the template and in your firefox, press Ctrl + U to view the html code of the page. This is what Play framework render the line listAction:

var listAction = function(options) {var pattern = '/user/save?username=:username&email=:email&dob=:dob&lGender=:lGender&gender=:gender&lastname=:lastname&firstname=:firstname&agreeTerm=:agreeTerm&password=:password&country=:country'; for(key in options) { pattern = pattern.replace(':'+key, options[key]); } return pattern } 

Do worry too much about the whole rendered function. You just need to know that in the end, it will return a pattern which contains the whole url with all the value inside the form. So, that means listAction will contain a url string, nothing else. Now you have a string url, what you need to do is putting it to the post function of Jquery and then waiting for the result from the controller.

5. Controller code:

Since I pointed the form action to the save function of User controller, now this is the save function

public static void save(
        @Required(message="Username is required") String username, 
	@Required(message="Password is required")String password, 
	@Required(message="Firstname is required") String firstname,
	@Required(message="Lastname is required") String lastname,
	String gender, String lGender,
	@Required(message="Email is required") String email,
	@Required(message="Birthdate is required")String dob,
	@Required(message="Country is required")String country,
	@Required(message="You have to agree with the terms")boolean agreeTerm) {
        
        if (models.User.find("byUsername", 
              username).first() != null) {
            renderText("Duplicate name");
        } else {
            models.User user = new models.User(username, 
                    password, firstname, 
                    lastname, gender, 
                    lGender, email, 
                    country, dob, 
                    agreeTerm);
            validation.valid(user);

            if (validation.hasErrors()) {
                renderText("Wrong values");
            }
        }
        .......       
}

So, that is all the things about ajax validation along with Play framework