Wednesday, July 9, 2014

Installing and enabling Java plugin for Firefox running on Linux



When you use Firefox browser to access websites which need Java plug-in to display its content, It always display grey background with a link to install plug-in if the plug-in is not install or it has not configured properly. This blog explain how to install and configure Java plug-in for Firefox running in Linux operating system.

Case study : Viewing live video from D-Link camera

I have a D-Link surveillance camera and I need to see live video from vendor provided web console. When I use Firefox browser, it require eithers ActiveX or Java to display. My OS is Ubuntu Linux, So I need Java plug-in to display live video.


Download JDK or JRE from Oracle website.



Depend on your OS and CPU architecture, download JDK or JRE of your platform. For Linux OS, Oracle provide two type of file RPM and zipped TAR file. I prefer tar file because I can extract into my home directory. Downloaded file is generally placed in Downloads directory under home directory.

Extract tar file.

I make programs directory under my home directory then I will extract tar into those directory.

$ cd
$ mkdir programs
$ cd ~/Downloads
$ tar zxvf jdk-8u5-linux-x64.tar.gz -C ~/programs

**Remember that your downloaded file name is depend on your selected Java version and your platform.

Update linux file index.

After install new program or place some files in Linux system, you should update file index so that you can find the file you want faster with locate command.

$ sudo updatedb

Searching for libnpjp2.so

The plug-in file which Firefox use to display Java plug-in is named libnpjp2.so. It come with JDK/JRE we have downloaded and extracted, let's find its location.

$ locate libnpjp2.so
/home/{your_account}/programs/jdk1.8.0_05/jre/lib/amd64/libnpjp2.so


Create symbolic link to Java plug-in.

Next step is creating symbolic link in Firefox plug-in directory to Java plug-in file.

$ cd /usr/lib/firefox/browser/plugins
$ sudo ln -s /home/{your_account}/programs/jdk1.8.0_05/jre/lib/amd64/libnpjp2.so .

***Note : File location for creating link is getting from previous step.

Restart Firefox and see what is changed.






The grey background disappear and Java animation logo takes place but Security alert is popped up. The reason is Java plug-in doesn't display content from untrusted sites by default, You have to add trusted URL list in Java control panel.


Configure Java security to allow plug-in running in browser. 

Go to bin directory of JRE and run JControl program.

$ cd /home/{your_account}/programs/jdk1.8.0_05/jre/bin
$ ./jcontrol


 Select the Security tab then click Edit Site List to add your trusted URLs and refresh page or restart Firefox again. Java plug-in should now working when visit trusted sites.






Monday, June 30, 2014

WildFly 8 : Sending Email using Gmail smtp server


Sending email is usually used as messaging tool to notify events occurred in corporate systems. JBoss WildFly 8 as Java EE implementer provides mechanism to send email by configuring remote email server information then get email session from JNDI.

This blog presents steps of configuring JNDI email session using Gmail as smtp server.

The convenient way to setup WildFly is by using web console.
Start WildFly application server, open web browser and go to http://localhost:9990 (Assume that you have already set authentication data for the web console)

After logged in, scroll down to select Socket Binding under General Configuration tab where we configure Gmail smtp server information.


Click View link to see details of standard-sockets information.


Select Outbound Remote tab then edit email server information.

Host : smtp.gmail.com
Port : 465

Remember that the name of Socket Binding is mail-smtp, we will use this name later to configure mail server.

Click Mail under Connector subsystems.


Click Add button to add new JNDI name for email session. Give the following information.
JNDI Name : java:jboss/mail/Gmail
Default From : (your gmail email address)

Click View link of added JNDI Name.


Add new Mail Server with the following information.

Socket Binding : mail-smtp
Type : smtp
UserName : your gmail email address
Password : your email password
Use SSL? : checked

Reload server configuration.



Now we have done configuration part, next we write the code to apply this JNDI email session.

Example EJB code to send email using configured JNDI email session.

import javax.annotation.Resource;
import javax.ejb.Asynchronous;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Session Bean implementation class GwMessage
 */
@Stateless
@LocalBean
public class GwMessage {
 private static final Logger log = LoggerFactory.getLogger(GwMessage.class);
 
 @Resource(mappedName="java:jboss/mail/Gmail")
 Session gmailSession;
 
 /**
     * Default constructor. 
     */
    public GwMessage() {
    }
    
    @Asynchronous
    public void sendEmail(String to, String from, String subject, String content) {
     
     log.info("Sending Email from " + from + " to " + to + " : " + subject);
     
  try {
 
   Message message = new MimeMessage(gmailSession);
   message.setFrom(new InternetAddress(from));
   message.setRecipients(Message.RecipientType.TO,
    InternetAddress.parse(to));
   message.setSubject(subject);
   message.setText(content);
 
   Transport.send(message);
 
   log.debug("Email was sent");
 
  } catch (MessagingException e) {
   log.error("Error while sending email : " + e.getMessage());
  }
    }

}

Description
Using resource injection to get email session.

@Resource(mappedName="java:jboss/mail/Gmail")
Session gmailSession;


Sending email is usually take time, @Asynchronous  help client not to wait until sending email has done, it just call and then go on immediately.


Friday, March 7, 2014

Web authentication with MySQL in WildFly8

Developer who want to migrate web application from Apache Tomcat to WildFly 8 , application server from JBoss,  may wonder how to setup their WildFly application server to support existing web applications which has been deployed on Apache Tomcat.

This article shows setting up WildFly application server to provide authentication using credential stored in MySQL database with MD5 hashing password.

Installing MySQL driver for WildFly application server.
Although MySQL driver can be installed by placing in deployments directory of server, In this blog I will install MySQL driver as core module by using the following steps.

Prepare module directory.
# cd wildfly8-Final/modules
# cd mkdir com
# cd com
# mkdir mysql
# cd mysql
# mkdir main

Then copy MySQL connector/J jar file (downloaded from mysql.com) into "main" directory.
# cd main
# cp ~/Downloads/mysql-connector-java-5.1.29-bin.jar .

Create module.xml in the "main" directory and add the following file contents.

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="com.mysql">
    <resources>
        <resource-root path="mysql-connector-java-5.1.29-bin.jar"/>
    </resources>
    <dependencies>
<module name="javax.api"/>
    </dependencies>
</module>

In the file standalone.xml, find <drivers> section then add driver configuration.

<drivers>
     <driver name="mysql" module="com.mysql"/>
</drivers>

Try to start WildFly then see the log file, message should show driver deployment and service status.

......Deploying non-JDBC-compliant driver class com.mysql.jdbc.Driver (version 5.1)
......Started Driver service with driver-name = mysql

Creating authentication database with users and roles information.

CREATE DATABASE authen_db;
USE authen_db;

CREATE TABLE `users` (
  `user_name` varchar(50) NOT NULL,
  `user_pass` varchar(50) DEFAULT NULL,
  `user_full_name` varchar(100)  DEFAULT NULL,
  PRIMARY KEY (`user_name`)
);

CREATE TABLE `user_roles` (
  `user_name` varchar(50)  NOT NULL,
  `role_name` varchar(50)  NOT NULL,
  PRIMARY KEY (`user_name`,`role_name`)
);

Add some user information for testing.

insert into users values('administrator', md5('admpass'), 'administrator');
insert into users values('john', md5('smtpwd'), 'John smith');
insert into users values('linda', md5('linpwd'), 'Linda smith');

insert into user_roles('administrator', 'admin');
insert into user_roles('john', 'admin');
insert into user_roles('john', 'callcenter');
insert into user_roles('linda', 'accounting');

Creating data source using by security sub system.

Creating data source is an easy task when using management web provided by WildFly.
Editing configuration file directly give the same working result. Here is what to be add into standalone.xml in standalone/configuration directory.

<subsystem xmlns="urn:jboss:domain:datasources:2.0">
      .
      .
      .
      <datasources>
                <datasource jndi-name="java:jboss/datasources/authenDb" pool-name="authenDb" enabled="true" use-java-context="true">
                    <connection-url>jdbc:mysql://authen-db-server:3306/authen_db</connection-url>
                    <driver>mysql</driver>
                    <pool>
                        <min-pool-size>1</min-pool-size>
                        <max-pool-size>5</max-pool-size>
                        <flush-strategy>IdleConnections</flush-strategy>
                    </pool>
                    <security>
                        <user-name>dbuser</user-name>
                        <password>dbpass</password>
                    </security>
                    <statement>
                        <track-statements>nowarn</track-statements>
                    </statement>
                </datasource>
      </datasources>
</subsystem>

Configuring security subsystem to apply MySQL database authentication.

In standalone.xml, add new security-domain into security subsystem. Parameter "principalsQuery" and "rolesQuery" is depend on your database schema.

<subsystem xmlns="urn:jboss:domain:security:1.2">
            <security-domains>
                 .
                 .
                 .
                 <security-domain name="webapp-authentication" cache-type="default">
                    <authentication>
                        <login-module code="Database" flag="required">
                            <module-option name="dsJndiName" value="java:jboss/datasources/authenDb"/>
                            <module-option name="principalsQuery" value="select user_pass from users where user_name=?"/>
                            <module-option name="rolesQuery" value="select role_name, 'Roles' from user_roles where user_name=?"/>
                            <module-option name="hashAlgorithm" value="MD5"/>
                            <module-option name="hashEncoding" value="hex"/>
                        </login-module>
                    </authentication>
                </security-domain>
            </security-domains>
</subsystem>

Defining security domain in jboss-web.xml

Create jboss-web.xml in WEB-INF directory with this content.

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>webapp-authentication</security-domain>
</jboss-web>


Configuring web application.

If you used standard login mechanism of Java EE when deploy in Tomcat, nothing have to be changed.

Sample authentication part of web.xml

  <login-config>
  <auth-method>BASIC</auth-method>
  </login-config>
  <security-constraint>
  <display-name>demo realm</display-name>
  <web-resource-collection>
  <web-resource-name>demo realm</web-resource-name>
  <url-pattern>/*</url-pattern>
  <http-method>GET</http-method>
  <http-method>POST</http-method>
 
  </web-resource-collection>
  <auth-constraint>
  <role-name>*</role-name>
  </auth-constraint>
  </security-constraint>
  <security-role>
  <role-name>*</role-name>
  </security-role>

Saturday, February 8, 2014

Setting subversion ignore files for Eclipse project





Eclipse and other IDE has its configuration files that are kept together with the project. This configuration files and directory are hidden and has dot prefix at the root of project directory.
     .setting
     .classpath
     .project

Some framework like a Maven also generate output directory in the root of project directory.
     target

All this files or directories should not be committed in to subversion so that other developers in the team can use shared source without conflict configuration.

To configure subversion to ignore project configuration files , do the following steps

     $ cd project_directory
     $ svn propedit svn:ignore .

For Ubuntu linux this command bring nano editor for adding the list of file or directories, just add all files that need not to be committed with your source codes.

     .settings
     .classpath
     .project
     target
     bin

Save file and then commit this list.

     $ svn commit -m "update ignore list"

Delete ignored files from subversion repository so that source code are none of ignored files but it still remember which files are not need to be uploaded from developer's machine.

Delete eclipse project and pretend to be a new member of developer team. Just check out the code and import into Eclipse again. IDE support files of Eclipse are created but will not be uploaded when you commit the code.



Monday, February 3, 2014

Setting TrueType fonts location for BIRT PDF report

When using TrueType fonts for PDF in BIRT report engine, you may see that some fonts like barcode or fonts for international languages are not appear correctly in PDF format report.

BIRT report engine is responsible for rendering exported format like PDF. It has configuration file for setting location of PDF fonts depend on you are running report in Eclipse BIRT designer or your java application.

If your report is run in BIRT designer, report engine will read configuration from fontsConfig.xml file under

     /eclipse_install_dir/plugins/org.eclipse.birt.report.engine.fonts_x.x.x.x

Open the file and look for <font-paths> section. Make sure you add your TrueType font location in the list.

For example TrueType fonts for thai language in Ubuntu linux are located in tlwg sub folder.

     <path path="/usr/share/fonts/truetype/tlwg"/>

But if your report is run in your java application that use BIRT report runtime engine in the form of libraries (jar files). The file fontsConfig.xml is packaged in

     org.eclipse.birt.runtime_4.3.1.xxxxxx.jar

Unfortunately, this file is signed and modifying the content of this file cause security exception in runtime. How I can fix this problem is to create symbolic link to the fonts (used in report) in the directory listed in original fontsConfig.xml

Case study
I use Ubuntu 12.04-TLS  and I want to use my Thai fonts in BIRT report with PDF format. I found that thai fonts are in

     /usr/share/fonts/truetype/tlwg

but it is not exists in fontsConfig.xml (in birt runtime jar file) . After checking the list of path in fontsConfig.xml, I've found the similar one.

     /usr/share/fonts/truetype/

The solution is creating symbolic link in this directory to target fonts. Assume wanted fonts is Norasi.ttf is in /usr/share/fonts/truetype/tlwg/.

     # cd /usr/share/fonts/truetype/
     # ln -s /usr/share/fonts/truetype/tlwg/Norasi.ttf    Norasi.ttf

After creating symbolic link, report engine should see this font and render report correctly.





Friday, July 19, 2013

JSF Validating multiple fields using custom validator

Writing custom validator to validate multiple fields in JSF.

JSF supports conversion and validation to separate user interface tasks from business logic. There are several useful ready to use conversion and validation tags bundled with JSF. If the web application need special conversion and validation, JSF provide interfaces to implement you own conversion and validation or you can declare method in the managed bean as the following code.

@ManagedBean
public class MyMBean implements Serializable {
...
...
public void myValidator(FacesContext context, UIComponent uiComponent, Object obj) throws ValidatorException {
   // your validation code
}
...
...
}

Assigning validator to input component in JSF pages.

<h:inputText id="fieldA" value="#{myMBean.fieldA}" validator="#{myMBean.myValidator}"/>

UIComponent and Object in custom validator declaration.
The Object parameter passed from JSF is a reference to input component which assigns this custom validator in its validator attribute (As example above, it refer to fieldA). The value of input component can be read by casting as String class.

String fieldAValue = (String)obj;

To find the value of other fields in the form, you can use UIComponent parameter to find target component and then get its value by using findComponent method as the following code.

UIInput fieldBInput = (UIInput) uiComponent.findComponent("fieldB");
String fieldBValue = (String) fieldBInput.getValue();

Example custom validator to verify changing password from user.
Requirements : Need a form to support user to change their password. User must enter the same password twice to confirm the new one.

Code for JSF form.

<h:form id="frmChangePassword">
   <h:panelGrid columns="3">
 <h:outputText value="New password" />
 <h:inputSecret id="password1" 
     value="#{changePassword.password1}" 
     required="true" 
     requiredMessage="Please enter password"/>
 <h:message for="password1" style="color:red"/>
 <h:outputText value="Confirm password" />
 <h:inputSecret  id="password2" 
     value="#{changePassword.password2}"
     required="true" 
     requiredMessage="Please enter password" 
     validator="#{changePassword.validatePassword}" 
     validatorMessage="Password mismatched!"/>
 <h:message for="password2" style="color:red"/>

 <h:commandButton value="Save" 
     action="#{changePassword.updatePassword}"/>
 <h:commandButton value="Cancel" action="main-page"  immediate="true"/>
 </h:panelGrid>
</h:form>

Code for Managed bean.

@ManagedBean
@ViewScoped
public class ChangePassword implements Serializable {
  private static final long serialVersionUID = 1L;
  private String password1;
  private String password2;

  public String getPassword1() {
     return password1;
  }
  public void setPassword1(String password1) {
     this.password1 = password1;
  }
  public String getPassword2() {
     return password2;
  }
  public void setPassword2(String password2) {
     this.password2 = password2;
  }

  public void validatePassword(FacesContext context, UIComponent uiComponent, Object obj) throws ValidatorException {

     UIInput uiPassword1 = (UIInput)uiComponent.findComponent("password1");
     String password1 = (String)uiPassword1.getValue();
     String password2 = (String)obj;

     if (!password2.equals(password1)) {
          throw new ValidatorException(new FacesMessage("password mismatch"));
     }

  public String updatePassword() {
     String username = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal().getName();
     System.out.println("Changing password for " + username);
     if (password1.equals(password2)) {
          // Do database related tasks;
          return "main-page";

     } else {
          return "change-password-error";
     }

  }
}







Sunday, July 14, 2013

How to adjust the value of Seconds_Behind_Master in MySQL replication.

Seconds_Behind_Master variable in MySQL replicate is usually used to determine how long the replicated database lagging from its master. You can get this value by using SHOW SLAVE STATUS command or by using MySQL Workbench this value is shown in TIME column of the SQL THREAD process.



You can see that sometime this value is non zero even the replica has done all SQL statements replicated from master. As described in MySQL document, this value is not accurate due to the calculation of this value is related to speed of the network, time stamp in binary log and the system clock.

If MySQL replication has been setup in high speed network environment, you can adjust the seconds_behind_master value by adjust system clock of master and slave to be equal.

For Linux system, adjust time by ntpdate command.

#ntpdate pool.ntp.org
14 Jul 09:03:53 ntpdate[28609]: step time server 176.31.45.67 offset 2.289779 sec

After updating system time in both master and slave machine, the value of Seconds_Behind_Master should be zero after slave done all SQL statement.