Struts nested tag Example

The tag library 忛ested?is included in Struts 1.1. In this tutorial we are going to explain what are the features of nested tag library and how you can use it. We can manage nested beans easily with the help of struts nested tag library. 


Nested tags are used in the nested context. The Nested tags and its supporting classes extends the base struts tags and making them possible to relate to each other in the nested fashion. In case of Nested tags the original logic of the tags does not change and all the references to beans and bean properties is managed in the nested context.


As far as bean is concerned, one is associated with another internally and access to all the beans are  through the current one. The beans that refers to another is the parent and the second related to the first one is its child. Here both ‘parent’ and ‘child’ denotes a hierarchical structure of beans. 
    
For example, Take an object which represents a Author. Each author  related to many book  .If this case was translated to bean objects, 
the author object would have a reference to the book objects he wrote, and each bunch object would hold a reference to
the chapters in the books.

The author object is the parent to the books object, and the books object is a child of the author object. The books object
is parent to its child chapters objects, and the child chapters objects children of the books object. The author is higher in
the hierarchy than the books, and the chapters lower in the hierarchy to the books.



Herbert Schildt
   
Teach Yourself C++
    Java: The Complete Reference, J2SE
    Struts: the complete reference
O’Reilly
   
.NET & XML
    ADO.NET in a Nutshell
    ADO: ActiveX Data Objects

Create a new struts 1.1 project to to understand nested tags.


Object Class Books
Create a class Books with properties id and name in the package roseindia.web.common.
Add a getter and setter method for each property.
Also add  a constructor that initialize the properties.

Books.java






package roseindia.web.common;
public class Books {

private int id;
private String name;

//constructors
public Books(){}

public Books(int id, String name){
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}


Object Class Authors
Create a second java class Authors in the same package roseindia.web.common.
Add two properties, id of type int and name of type String and one property books of type Collection, which holds a list of books.
Add a getter and setter method for each property.
Also add  a constructor that initialize the properties.

Authors.java






package roseindia.web.common;
import java.util.*;
public class Authors {
	private int id;
private String name;
	//books collection
private Collection books;
	//constructors
public Authors() {}
public Authors(int id, String name, Collection books){
this.id = id;
this.name = name;
this.books = books;
}
	public Collection getBooks() {
return books;
}
public void setBooks(Collection books) {
this.books = books;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}


Action form class AuthorsBooksForm
Create a java class AuthorsBooksForm in the package roseindia.web.struts.form, which extends the class ActionForm of struts.
Add a property authors of type Authors .
Add a getter and setter method for the property authors .

Implement the reset() method of the ActionForm class. 

AuthorsBooksForm.java






package roseindia.web.struts.form;
import java.util.*;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import roseindia.web.common.Authors;
import roseindia.web.common.Books;
public class AuthorsBooksForm extends ActionForm {
	Authors authors;

public void setAuthors(Authors authors) {
this.authors = authors;
}
	public Authors getAuthors() {
return authors;
}
	public void reset(ActionMapping mapping,HttpServletRequest request) {
		//initial a dummy collection of books
Collection books = new ArrayList();
		books.add(new Books(1, “Teach Yourself C++”));
books.add(new Books(2, “Java: The Complete Reference, J2SE”));
books.add(new Books(3, “Struts: The Complete Reference”));

//initial a dummy authors
authors = new Authors(1, “Herbert Schildt”, books);

}
}


Action class AuthorsBooksAction 

Create a java class AuthorsBooksAction in the package roseindia.web.struts.action, which extends the class Action of struts.
Return the forward example.

AuthorsBooksAction.java






package roseindia.web.struts.action;
import roseindia.web.struts.form.AuthorsBooksForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class AuthorsBooksAction extends Action {

public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
AuthorsBooksForm booksForm = (AuthorsBooksForm) form;
		return mapping.findForward(“books”);
}
}


The JSP file


Create a new JSP file authorsbooks.jsp.
Add the reference to the tag library nested at the top of the file.


authorsbooks.jsp






<%@ page language=”java”%>
<%@ taglib uri=”/tags/struts-bean” prefix=”bean” %>
<%@ taglib uri=”/tags/struts-html” prefix=”html” %>
<%@ taglib uri=”/tags/struts-logic” prefix=”logic” %>
<%@ taglib uri=”/tags/struts-nested” prefix=”nested”%>
<html>
<head>
<title>Struts nested tag Example</title>
</head>
<body>
<h1>Struts nested tag Example</h1>
	  <b>Author and his books:</b>
<html:form action=”/example” method=”post”>
			<nested:nest property=”authors”>
				<b><nested:write property=”name”/> </b>
<nested:iterate property=”books”>
					<ul><li><nested:write property=”name”/></li></ul>
</nested:iterate>
</nested:nest>

		</html:form>
</body>
</html>


Configure the struts-config.xml


Open the struts-config.xml and add the form bean and action mapping.


struts-config.xml






 <form-beans>
<form-bean name=”AuthorsBooksForm”
type=”roseindia.web.struts.form.AuthorsBooksForm” />
</form-beans>
<action-mappings>
<action
path=”/example”
type=”roseindia.web.struts.action.AuthorsBooksAction”
input=”/pages/user/authorsbooks.jsp”
name=”AuthorsBooksForm”
scope=”request”
validate=”false”>
<forward name=”example” path=”/pages/user/authorsbooks.jsp” />
</action>
</action-mappings>



Output:
To view the output run the authorsbooks.jsp from the browser.

Developing Struts PlugIn


This article shows you how to develop custom Struts PlugIn and incorporate in your Struts Web Applications. After completing this tutorial you will be able to create your own custom PlugIn for your web application. Struts PlugIn allows the programmer to enhance their web applications. There are many PlugIns available for struts e.g. Struts Tiles PlugIn, Struts Hibernate PlugIn, Struts Spring PlugIn etc. Beside these available PlugIn you can create your own PlugIn.


Understanding PlugIn


Struts PlugIns are configured using the <plug-in> element within the Struts configuration file. This element has only one valid attribute, ‘className’, which is the fully qualified name of the Java class which implements the org.apache.struts.action.PlugIn interface.


For PlugIns that require configuration themselves, the nested <set-property> element is available.


The plug-in tag in the struts-config.xml file is used to declare the PlugIn to be loaded at the time of server start-up. Following example shows how to declare the Tiles PlugIn:


<plug-in className=”org.apache.struts.tiles.TilesPlugin”>
    <set-property
        property=”definitions-config”
           value=”/WEB-INF/tiles-defs.xml”/>
</plug-in>


The above declaration instructs the struts to load and initialize the Tiles plugin for your application on startup. 


 


 


Writing Struts PlugIn Java Code


In this example we write HelloWorld Struts PlugIn example that will give you idea about creating, configuring and checking Struts PlugIn. Our HelloWorld Stuts PlugIn contains a method called Say Hello, which simply returns HelloWorld message.


Here is code of HelloWorld Struts Plugin: 






package roseindia.net.plugin;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.apache.struts.action.PlugIn;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.config.ModuleConfig;

/**
@author Deepak Kumar
* @Web http://www.roseindia.net
* @Email roseindia_net@yahoo.com
*/


public class HelloWorldStrutsPlugin implements PlugIn {


    public static final String PLUGIN_NAME_KEY 
            = HelloWorldStrutsPlugin.class.getName();

   public void destroy() {
      System.out.println(“Destroying Hello World PlugIn”);
   }

   public void init(ActionServlet servlet, ModuleConfig config
throws ServletException {
      System.out.println(“Initializing Hello World PlugIn”);
   ServletContext context = null;
   context = servlet.getServletContext();
   HelloWorldStrutsPlugin objPlugin = new HelloWorldStrutsPlugin();
   context.setAttribute(PLUGIN_NAME_KEY, objPlugin);

   }

  public String sayHello(){
    System.out.println(“Hello Plugin”);
    return “Hello Plugin”;
  }
  
}


Configuring PlugIn


To configure the plugin add the following line your struts-config.xml file.


<plug-in className=”roseindia.net.plugin.HelloWorldStrutsPlugin”>
</plug-in>


Calling PlugIn From JSP Page


Here is the code for calling our PlugIn from jsp page.






<%@page contentType=”text/html” import=”java.util.*,roseindia.net.plugin.*” %>
<%

ServletContext servletContext = this.getServletContext();


HelloWorldStrutsPlugin plugin= (HelloWorldStrutsPlugin) servletContext.getAttribute
(HelloWorldStrutsPlugin.PLUGIN_NAME_KEY);

String strMessage = plugin.sayHello();


%>

Message From Plugin: <%=strMessage%>


Building and Testing


Use ant tool to build the application and then deploy on the server. Enter the url http://localhost:8080/strutstutorial/pages/plugin.jsp in your browser. It display “Hello Plugin” message. Your server console also should display “Hello Plugin” message.


In this section we learnt how to develop simple struts plugin, configure, deploy and test.

STRUTS INTERNATIONALIZATION

In this tutorial we shall see how to implement Internationalization (abbreviated as I18N) in Struts.

The Multinational Corporations have their branches in various parts of the world. so, they must provide products and services to their clients and customers in their traditional way. The customers will expect the product to work in their native languages especially the date, time, currency etc.,. So, the we should not make any assumptions about their clients region or language. If such assumptions become invalid, we have to re-engineer the applications.

Internationalization or I18N is the process of designing the software to support multiple languages and regions, so that we don’t need to re-engineer the applications every language or country needs to be supported.

Struts provides various locale sensitive JSP tags which can be used to make the applications simpler. With this short introduction we shall see how to implement i18n in a Simple JSP file of Struts.

g:\>md localedemo
g:\>cd localedemo
g:\localedemo>edit localedemo.jsp

// g:\localedemo\localedemo.jsp

<%@ page language=”java” %>

<%@ taglib uri=”/WEB-INF/struts-html.tld” prefix=”html” %>
<%@ taglib uri=”/WEB-INF/struts-bean.tld” prefix=”bean” %>
<%@ taglib uri=”/WEB-INF/struts-logic.tld” prefix=”logic” %>

<html:html locale=”true”>
<body bgcolor=pink>

<bean:message key=”index.info” />

</body>
</html:html>
————————————–



Next copy struts-blank.war to f:\tomcat41\webapps and start the tomcat with JAVA_HOME as jdk1.4. A folder named struts-blank will be created. Rename the folder as localedemo. Copy the above JSP file to f:\tomcat41\webapps\localedemo.

Now we have to edit the property files for various locales. The struts framework(struts1.1) provides a property file named application.properties. It is present in the folder f:\tomcat41\webapps\localedemo\web-inf\classes\resources. We have to add our own property file in this folder only. Our property file much be named along with the language code

For example the language code of
     1. German – de
     2. Spanish – es
     3. English – en
     4. Korean – ko
     5. French – fr
     6. Italy – it

So, when we write i18n message in German language it must be placed in property file named application_de.properties and all the properties files must be present in the resources folder only. Also when we write the property file of a particular language it need not be of the same language. For example we can create application_de.properties and write the message in french or english. In fact, the message does not depend on any language. It is a simple key value pair. The message we give for the key is just substituted. The property file to locate the value of key depends on the language settings of the browser. For this example, we will write four properties file as follows.

f:\tomcat41\webapps\localedemo\web-inf\classes\resources\ application_de.properties

index.info=GERMANY
———————————————————
f:\tomcat41\webapps\localedemo\web-inf\classes\resources\ application_es.properties

index.info=SPAIN
———————————————————–
f:\tomcat41\webapps\localedemo\web-inf\classes\resources\ application_en.properties

index.info=ENGLISH
———————————————————–
f:\tomcat41\webapps\localedemo\web-inf\classes\resources\ application_fr.properties

index.info=FRANCE
————————————————————
Also append this text in the application.properties file
    index.info=STRUTS TUTORIAL.

Now we have to add entry in the
struts-config.xml file for all the properties files. The entry and its corresponding portion is shown below.

<!– Message Resources Definitions –>

        <message-resources parameter=”resources.application_fr“/>
        <message-resources parameter=”resources.application_es“/>
        <message-resources parameter=”resources.application_en“/>
        <message-resources parameter=”resources.application_de“/>
        <message-resources parameter=”resources.application“/>

Now restart the Tomcat server. Open the Internet Explorer and type the URL as http://localhost:8080/localedemo/localedemo.jsp. We will get the message ‘ENGLAND’. This is because our default browser language is ‘United States English’.

Now we have to change the language settings of the browser to change the locale. For that, Open a new Internet Explorer, goto ‘Tools’ menu and select the ‘Internet Options’. In the ‘Internet Option’ dialog box, select ‘General’ tab and click the ‘Languages…’ button. We will get ‘Language Preference’ dialog box. There click ‘Add…’ button and add the languages. For this example add English, Spanish, German and French. Here we have languages specific to particular region. For example we have, French Belgium, French Canada, French France etc., we can select any one of these in all cases. Next select ‘German’ and by using the ‘Move up’ button, place it on the top. Now type the URL as http://localhost:8080/localedemo/localedemo.jsp. We will get the message ‘GERMAN’ Similarly place ‘Spanish’ and ‘French’ at the top, we will get the message ‘SPAIN’ and ‘FRANCE’ respectively.
—————————————————————————

Configuring Struts DataSource Manager on Tomcat 5

This tutorial shows you how you can configure Struts DataSource Manager on the Tomcat 5.5.9 server. We will use struts 1.2.7 in this tutorial. In this tutorial we will configure Struts DataSource Manager to use MySQL Database and use the connection provided by Struts DataSource in action class.


Downloading and Installing Tomcat 5.5.9
Download jakarta-tomcat-5.5.9 from http://jakarta.apache.org/tomcat/. Install it on your machine. Run and test the pages that comes with the tomcat.


Download Struts
Download Struts struts-1.2.7 from http://struts.apache.org/download.cgi and unzip it to your favorite directory. Go to the struts-1.2.7\webapps directory and then unzip struts-blank.war file. We will use this file to write our tutorial.


Download MySQL JDBC Driver
Download mysql-connector-java-3.0.16-ga-bin.jar from here mysql-connector-java-3.0.16-ga-bin.jar or you can download and use the latest version of mysql jdbc driver. Copy the JDBC driver file (mysql-connector-java-3.0.16-ga-bin.jar or latest version) to the jakarta-tomcat-5.5.9\common\lib directory of your tomcat installation. This will add the MySQL JDBC driver to the tomcat server.


Creating MySQL Database
In this tutorial I am using MySQL server installed on my local machine. You can download and install MySQL on your local machine and use for this tutorial. If you already have MySQL server then you can use the existing MySQL server.


Create database “strutsdatabase” on the MySQL server and then run the following query to create test table.






CREATE TABLE `test` (
`username` varchar(20) NOT NULL default ”
) TYPE=MyISAM;

/*Data for the table `test` */

insert into `test` values (‘rajesh’),(‘George’),(‘Vikas’),(‘Prakash’),(‘Mahesh’);


Above query creates test table and then populates the table with data.


Configuring Struts Application
Now create a directory “strutsdatabase” in the jakarta-tomcat-5.5.9\webapps\ directory and copy the content of struts-blank application (unzipped above) in the strutsdatabase directory.


Now start the tomcat and try to access the strutsdatabase application by typing the url http://localhost:8080/strutsdatabase in browser. Your browser should display the welcome page. After testing shutdown the tomcat server.


Configuring Struts DataSource Manager
The Struts DataSource manager makes it easy for your Action class get the database connection. To configure the Stuts DataSource Manager we will uncomment the <data-sources> entry in the struts-config.xml.


Uncomment and then <data-sources> entry in the struts-config.xml and then change the line


org.apache.commons.dbcp.BasicDataSource” to “org.apache.tomcat.dbcp.dbcp.BasicDataSource“. In tomcat 5.5.9 dbcp classes are packaged in naming-factory-dbcp.jar archieve, so we are using “org.apache.tomcat.dbcp.dbcp.BasicDataSource” instead of “org.apache.commons.dbcp.BasicDataSource”. After this change the database dirver, database url and passwor in the <data-sources> tag.


You <data-source> element should look like:






<data-sources>
<data-source type=”org.apache.tomcat.dbcp.dbcp.BasicDataSource“>
<set-property
property=”driverClassName”
value=”com.mysql.jdbc.Driver” />
<set-property
property=”url”
value=”jdbc:mysql://localhost:3306/strutsdatabase?autoReconnect=true” />
<set-property
property=”username”
value=”root” />
<set-property
property=”password”
value=”” />
<set-property
property=”maxActive”
value=”10″ />
<set-property
property=”maxWait”
value=”5000″ />
<set-property
property=”defaultAutoCommit”
value=”false” />
<set-property
property=”defaultReadOnly”
value=”false” />
<set-property
property=”validationQuery”
value=”SELECT COUNT(*) FROM test” />
</data-source>
</data-sources>

Create action Class to Test the DataSource
Now we will write the code of Action class for getting the connection form DataSource:





package test;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import java.sql.*;

public class TestDataSource extends Action
{
  public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse responsethrows Exception{

       javax.sql.DataSource dataSource;
       java.sql.Connection myConnection=null;
       try {
        dataSource = getDataSource(request);
        myConnection = dataSource.getConnection();
        Statement stmt=myConnection.createStatement();
        ResultSet rst=stmt.executeQuery(“select username from test”);
        System.out.println(“******************************************”);
        System.out.println(“********Out Put from TestDataSource ******”);
        while(rst.next()){
        System.out.println(“User Name is: ” + rst.getString(“username”));
        }
        System.out.println(“******************************************”);
        rst.close();
        stmt.close();
        // do what you wish with myConnection
       catch (SQLException sqle) {
        getServlet().log(“Connection.process”, sqle);
       finally {
        //enclose this in a finally block to make
        //sure the connection is closed
        try {
           myConnection.close();
        catch (SQLException e) {
           getServlet().log(“Connection.close”, e);
        }
         }


      return mapping.findForward(“success”);
  }

Following code is used to get the data source and then connection from Struts DataSource:


dataSource = getDataSource(request);
myConnection = dataSource.getConnection();


Save this file(TestDataSource.java)  into jakarta-tomcat-5.5.9\webapps\strutsdatabase\WEB-INF\src\java\test directory. Add the servlet API into class path. Then open dos prompt and navigate to jakarta-tomcat-5.5.9\webapps\strutsdatabase\WEB-INF\src\ directory and issue run ant. This will compile the action class (TestDataSource.java) and copy it to the classes directory of the webapplication.


Creating Action Mapping struts-config.xml
Now add the following action mapping into the struts-config.xml:






<action
      path=”/DataSource”
      type=”test.TestDataSource”>
      <forward name=”success” path=”/success.jsp”/>
</action>

Running and testing
Start tomcat and browse the url http://localhost:8080/strutsdatabase/DataSource.do. Your browser should show the following output.



Now check tomcat console, it should display records fetched from database.


You can download my struts-config.xml from here.


Note: The DataSource manager is being retained in Struts 1.x for backward compatibility but may not be retained in Struts 2.x or later.

STRUTS ACTION – AGGREGATING ACTIONS IN STRUTS

If you are a Struts developer then you might have experienced the pain of writing huge number of Action classes for your project. The latest version of struts provides classes using which you can aggregate a related set of actions into a single unified action. In this article we will see how to achieve this. Struts provides four important classes for this purpose. These classes are called as Dispatchers. The important Dispatchers that struts provides includes : DispatchAction, ActionDispatcher , LookupDispatchAction and MappingDispatchAction.

All these classes can be found in the package org.apache.struts.actions. Let us look in to each of these in detail. Our examples use the simple CRUD actions.

DispatchAction: In this type of aggregation, the action class must extend DispatchAction class as shown.

public final class CRUDDispatchAction extends DispatchAction {

public ActionForward create(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
return (mapping.findForward(“success”));
}
… 


and the action mapping will be as 

<action path=”/crudDispatchAction” type=”com.companyname.projname.CRUDDispatchAction” name=”formName” scope=”request” input=” homeDef” parameter=”methodToCall”>
<forward name=”success” path=”targetDefName”/>
</action>


in your jsp you can call this action as 

<html:link action=”crudDispatchAction?methodToCall=create”>Create</html:link>
… 


Observe that the above class extends DispatchAction and so you cannot use this method if your class already extends your (some) super class (eg., the class where the session is validated/invalidated). Here the user has to send a query string variable (methodToCall) to set the action name to call.

ActionDispatcher: This flavor of aggregation is same as DispatchAction except that we need not extend ActionDispatcher, so we can use this method even if our class extends a super class. The following code snippet shows this scenario.


public final class CRUDActionDispatcher extends Action {

protected ActionDispatcher dispatcher = new ActionDispatcher(this, ActionDispatcher.DEFAULT_FLAVOR);

public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
return dispatcher.execute(mapping, form, request, response);
}
The DEFAULT_FLAVOR field suggests that the default parameter is “method” if none is specified as parameter in struts-config.xml (eg,. methodToCall).
ActionDispatcher flavor also needs methodToCall parameter to be set (using hidden variable or a query string) as in case of DispatchAction.

LookupDispatchAction: This type of aggregation is useful in situations where in you have multiple submit buttons in a single form. The class must extend LookupDispatchAction. However, the great thing about this type is that its java script free. That means, you need not set any hidden variables or pass query string however, you must use submit buttons as shown.

<html:submit property=”submit”><bean:message key=”button.create”/></html: submit >
<html:submit property=”submit”><bean:message key=”button.read”/></html: submit >
… 
The example Action class will be as follows 

public class CRUDLookUpDispatchAction extends LookupDispatchAction {
protected Map getKeyMethodMap() {
Map map = new HashMap();
map.put(“button.create”, “create”);
?nbsp;
return map;
}
public ActionForward create(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
return (mapping.findForward(“success”));
}
Observe the getKeyMethodMap() method. The submit button names are specified in a Map and their keys comes from MessageResources file. Struts picks up the name from this file and redirects it to the value specified in the Map. The calling code in jsp however has multiple submit buttons only differing in their names.

MappingDispatchAction: This aggregation extends MappingDispatchAction class. This is the most useful type among the four types available. But as seen in other cases, you can use this type only when your action does not extend any other action. The good thing about this type is that the action mappings can differ and so need not be the same as in all other cases. To illustrate this consider the below mappings.

<action path=”/createMappingAction” type=”com.bodhtree.CRUDMappingDispatchAction” scope=”request” input=”homeDef” parameter=”create”>
<forward name=”success” path=”targetDef”/>
</action>
<action path=”/readMappingAction” type=”com.bodhtree.CRUDMappingDispatchAction” name=” formName” scope=”request” input=”homeDef” parameter=” read”>
<forward name=”success” path=”targetDef”/>
</action> 


Notice that in the first action mapping, there is no form bean while in the second the bean name is specified. This means that the user has the flexibility to change the mapping according to his needs and hence not been contained to use a constant mapping for all the CRUD actions. Note that in all the other types of aggregations, we must use the same mapping for all the CRUD actions.

Conclusion: Each of these types has their own pros and cons. DispatchAction is the default type which uses java script and we must extend DispatchAction to use it, ActionDispatcher is same as DispathAction except that we do not extend any action , LookupDispatchAction gives the flexibility to use multiple submit buttons while MappingDispatchAction allows us to change the action mappings according to our need. So each one of these has a particular usage and which one to use depends on the user requirement.

NOD32最新升級ID nod32升级服务器 nod32下载 nod32破解版 nod32注册码


2007年9月6號

 

UserName: AV-6476241
Password: n1d7xtk7ko

UserName: AV-6488086
Password: it9gqnd33a

UserName: AV-6471366
Password: 3gufs98wcq

UserName: AV-6258073
Password: y17dhcb1f4

UserName: AV-6454441
Password: 2mo24goes2

UserName: AV-6360500
Password: 73ec6ds05r

UserName: AV-6069610
Password: p96wc7bfbh

UserName: AV-6516992
Password: ise0qj9a8y

How to fix “java.lang.OutOfMemoryError: unable to create new native thread”


I recently came across this exception on a couple of java systems that use many threads  java.lang.OutOfMemoryError: unable to create new native thread. The strange thing was that the JVM had been assigned a lot of memory (1.5GB) and that it had at least half the memory available. Michele found this article that points out that the more memory you give to the JVM the more likely you are to get java.lang.OutOfMemoryError: unable to create new native thread exceptions when you have many threads.


Which makes perfect sense when you think about it. Each 32 bit process on Windows has 2GB “available” memory as 2GB is reserved to Windows. In my case the JVM grabbed 1.5 GB leaving 500MB. Part of the 500MB was used to map system dlls etc in memory so less than 400 MB was left. Now to the crucial point: When you create a thread in java it creates a Thread object in the JVM memory but it also creates a operating system thread. The operating system creates the thread with a thread stack in the 400MB that is left, not in the 1.5 GB allocated in the JVM. Java 1.4 uses a default stack size of 256kb but Java 1.5 uses a 1MB stack per thread. So, in the 400MB left to process I could only generate ~400 threads. Absurd but true: to create more threads you have to reduce the memory allocated to the JVM. Another option is to host the JVM in your own process using JNI.


This formula gives a decent estimate for the number of threads you can create: 
(MaxProcessMemory – JVMMemory – ReservedOsMemory) / (ThreadStackSize) = Number of threads


For Java 1.5 I get the following results assuming that the OS reserves about 120MB:
1.5GB allocated to JVM: (2GB-1.5Gb-120MB)/(1MB) = ~380 threads
1.0GB allocated to JVM: (2GB-1.0Gb-120MB)/(1MB) = ~880 threads


Java 1.4 uses 256kb for the thread stack which lets you create a lot more threads:
1.5GB allocated to JVM: ~1520 threads
1.0GB allocated to JVM: ~3520 threads


I have not tried the 3GB switch but it should in theory let you create more threads.

Javascript Dates-The Complete Reference

Javascript Dates-The Complete Reference


Filed: Mon, Apr 23 2007 under Programming|| Tags: reference date javascript julian countdown

Of all the core Javascript objects, I find Dates to be the most fascinating. Once you learn a few small tricks everything about Javascript Dates just seem to fall into place and you find that there’s really nothing at all that you can’t do with them, quickly, and easily.

This reference will cover the Javascript Date Object, how it stores Dates, how you can manipulate them, create calendars, countdown timers, prototype them to add your own functionality, as well as provide a complete method reference.

Julian Dates


Julian Dates are a method of referencing time and dates based on how much time has passed since an arbitrary number in the past. For instance,

149 days have presently passed this year. If we know that January 1 begins on a

Monday , then we know that day 2 represents a

Tuesday in January. If we know there are 31 days in January then we know that day 32 represents the first of February and we can figure out that February 1st fell on a

Thursday.

Javascript (and most languages) handle dates exactly as described above, only in much grander fashion. The epoch or starting point of Javascript’s date system isn’t January 1 of this year, but rather January 1, 1970 Greenwich Mean Time, and it doesn’t count just days! No Javascript counts the number of milliseconds that have passed since January 1, 1970 and presently that number is 1,180,503,305,390.

Midnight, January 1, 1970 GMT is represented as zero by Javascript. Positive numbers indicate dates after 1970 and negative numbers indicate dates prior to 1970. For instance -1000 represents 11:59:59pm, December 31, 1969. Remember Javascript counts in milliseconds and there are 1000 milliseconds in a single second so -1000 represents 1 second.

By a great coincidence Unix also uses January 1, 1970 as it’s epoch date which means a timestamp in Javascript will match a timestamp on your server as long as you take some care with the timezones!

It will be quite a while before humanity has to worry about running out of dates! Javascript can readily handle around 285,616 years on either side of the 1970 epoch.

Creating A New Date (Parsed)


To create a new Date all you have to do is to ask for one!

var myFirstDate = new Date();

This will create a new date object and since we did not specify a specific date or time, the date will be equal to the instant it was created.

The Javascript Date Object has a very powerful date parser. While there are several ways to create and set Dates. The one you’re most likely to use is simply to specify the date itself, as a string, when creating a new date.

var myDate = new Date(‘January 16, 1988’);

Since we didn’t specify a time the Date which is created will be for midnight in the browser’s timezone on January 16, 1988.

var myDate = new Date(‘January 16, 1988 2:54:16 pm’);

Here we specify a specific time (note that there’s a space between the time and pm). Since we didn’t specify a timezone the browser will use the user’s timezone. We could also have used millitary time (14:54:16).

Here we’ll actually specify a time zone GMT in this case and below we’ll print it out.

var myDate = new Date(‘January 16, 1988 2:54:16 pm GMT’);


Sat Jan 16 22:54:16 UTC+0800 1988

Unless you actually live in the Greenwich Mean Timezone, the date requested and the date printed are unlikely to match. The created date is actually 2:54:16 in the GMT timezone, however when we printed the date out, since we didn’t specify anything special, the date was printed in the Browser’s time zone so the browser did a little conversion for us to ensure the time we printed was the ACTUAL time relative to the browser.

That’s a little confusing so let’s try for something different. Every New Years Eve, the city of New York holds a big celebration and the ball is dropped at precisely midnight in the eastern timezone. So lets create a date for that event.

var myDate = new Date(‘January 1, 2000 EST’);

Since we didn’t specify a time, Javascript will assume midnight for us, we did specify a time zone so the actual time will be midnight in the eastern time zone.

Now when we print the date out we’ll get that little timezone conversion and you can see what time the ball will be dropping in your timezone! (of course people in the eastern timezone will see the “correct” time).

Sat Jan 1 13:00:00 UTC+0800 2000

Creating A New Date (arguments)


You can also create a new date by passing the date values as arugments to the Date object. The arguments are Year, Month, Date and optionally hours, minutes, seconds, and milliseconds. The first argument, year, is special. If it’s a string the Date object will try to parse it (see previous section), if it’s a long integer it will try to use it as a julian number. If there are more than one argument it will build the date from your supplied arguments.

var d1 = new Date(‘January 1, 1970’); // Date as a parse
var d2 = new Date(0);                 // Date as a julian number
var d3 = new Date(1970, 0, 1);        // Date as arguments

Notice we use zero as the month when creating d3, that’s because Javascript months go from 0 to 11 where January is zero. This is a pretty big gotcha if you’re not careful!

The argument list is as follows…

dateVar = new Date(year, month, date[, hours[, minutes[, seconds[,ms]]]]);

Working With Julian Day Numbers


Working with Julian Dates requires division and modulus. Division will discard the portion of the date you no longer need and modulus (which is the remainder of division) will return the portion of the date you are looking for.

Most people don’t need milliseconds when doing date calculation, so we just divide the Julian Date Number by 1,000. So if we have a Julian Day Number of 1,177,303,066,354 then dividing this by 1,000 will give us a day number of 1,177,303,066 — a number which no longer holds information about the milliseconds in the date.

To get the number of seconds this represents, we take the modulus of 60 because there are 60 seconds in a minute.

var dayNumber = 1177303066;
var seconds = dayNumber % 60;  // seconds=46

Now that we have the number of seconds we discard the seconds from the Julian date by dividing it by 60.

var dayNumber = 1177303066;
var seconds = dayNumber % 60;  // seconds=46
dayNumber
= dayNumber/60;      // dayNumber = 19,621,717

So now our day number has been stripped of milliseconds and seconds. We can find out how many minutes the number represents by taking the modulus of 60 since there are 60 minutes in an hour.

var dayNumber = 1177303066;
var seconds = dayNumber % 60;  // seconds=46
dayNumber
= dayNumber/60;      // dayNumber = 19,621,717
var minutes = dayNumber % 60;  // minutes=37  

And we can discard the minutes from the original number by dividing it by 60. What remains are hours and days. We can get the hours by taking the modulus of 24 since there are 24 hours in a day. Then divide the daynumber by 24 to discard the hours, leaving only the number of days.

var dayNumber = 1177303066;
var seconds = dayNumber % 60;  // seconds=46
dayNumber
= dayNumber/60;      // dayNumber = 19,621,717
var minutes = dayNumber % 60;  // minutes=37
dayNumber
= dayNumber/60;      // dayNumber = 327,028
var hours = dayNumber % 24;    // hours = 4
dayNumber
= dayNumber/24       // dayNumber = 13,626

Or 13,624 days between January 1, 1970 and

Mon Apr 23 12:37:46 UTC+0800 2007

Countdown Timers In Javascript


In the previous section we broke a day number out into its component milliseconds, seconds, minutes, hours, and days. The number we used was the number of milliseconds that had elapsed since January 1, 1970. But we could just as easily have used another date. Lets take the difference between now and the end of the year.

var now = new Date();
var newYear = new Date(‘January 1, ‘+(now.getFullYear()+1));
var diff=newYearnow;

This code creates two julian dates, “now” and “newYear”. By subtracting “now” from “newYear” we get an integer which represents the difference between the two dates, specifically:

18,613,597,250.

We can use division and modulus to extract the time from this number just like we did in the previous section only now we’re computing the difference between now and the new year instead of a date and January 1, 1970.

This article is generating “now” and “newYear” in real-time so the values below are the actual values until the new year!

var now = new Date();
var newYear = new Date(‘January 1, ‘+(now.getFullYear()+1));
var diff=newYearnow;
var milliseconds=Math.floor(diff % 1000);  
    diff
=diff/1000;            
var seconds=Math.floor(diff % 60);
    diff
=diff/60;
var minutes=Math.floor(diff % 60);
    diff
=diff/60;
var hours=Math.floor(diff % 24);
    diff
=diff/24;
var days=Math.floor(diff);

This gives us a value of

215 Days, 10 hours, 26 minutes, 37 seconds, until Tue Jan 1 00:00:00 UTC+0800 2008.

Making a Timer


In the example above now is equal to the instant it is created while newYear is a constant value, always equal to January 1 of next year. So it’s actually very easy to make a timer. All we have to do is turn the code above into a function, set up a setTimeout command, and create a html division somewhere on the page to hold our timer. Here’s the new code!

<!– This span is where the countdown timer will appear –>
<div id=‘countdown’></div>

<script type=“text/javascript”>
// Here’s our countdown function.
function happyNewYear() {
   
var now = new Date();
   
var newYear = new Date(‘January 1, ‘+(now.getFullYear()+1));
   
var diff=newYearnow;
   
var milliseconds=Math.floor(diff % 1000);  
       diff
=diff/1000;            
   
var seconds=Math.floor(diff % 60);
       diff
=diff/60;
   
var minutes=Math.floor(diff % 60);
       diff
=diff/60;
   
var hours=Math.floor(diff % 24);
       diff
=diff/24;
   
var days=Math.floor(diff);
   
   
// We’ll build a display string instead of doing document.writeln
   
var outStr = days + ‘ days, ‘ + hours+ ‘ hours, ‘ + minutes;
       outStr
+= ‘ minutes, ‘ + seconds + ‘ seconds until the new year!’;

   
// Insert our display string into the countdown span.
   document
.getElementById(‘countdown’).innerHTML=outStr;

   
// call this function again in exactly 1 second.  
   setTimeout
(“happyNewYear()”,1000);
}

// call the countdown function (will start the timer)
happyNewYear
();  
</script>

When the function is called (every second), now is always set to the current, ever advancing date, while the newYear always remains a constant. So the function works to countdown the passing time to the destination date (new year).

And here’s the result! 215 days, 10 hours, 24 minutes, 55 seconds until the new year!

Does the time appear a bit off? Maybe because right now you’re in Daylight time and the new year is in daylight savings time! If this is the case, once everyone falls back the timer will again be in sync with your expectations!

Making A Clock


Making a clock is very similar to making a countdown timer. All we have to do is to create a new date and get it’s hours, minutes, and seconds.

<!– This span is where the clock will appear –>
<div id=‘clockDiv’></div>

<script type=“text/javascript”>
function clock() {
   
var now = new Date();
   
var outStr = now.getHours()+‘:’+now.getMinutes()+‘:’+now.getSeconds();
   document
.getElementById(‘clockDiv’).innerHTML=outStr;
   setTimeout
(‘clock()’,1000);
}
clock
();
</script>

And the result (in military time): 13:35:4

Getting The Number Of Days In A Month


Javascript has a little quirk where a date of zero will set the date to be the last day of the previous month. Likewise is there are 30 days in a month and you set a date of 31 it will be the 1st day of the next month, a date of 40 would be the 10th day of the next month. This can lead to some very weird funkiness if you’re not careful but we can definitely exploit this for a useful prototype which will give us the number of days in a specific month. We’ll do this up as a prototype so it’s available to all our Dates.

Date.prototype.daysInMonth = function () {
   
return new Date(this.getFullYear(), this.getMonth()+1, 0).getDate()
}

var d = new Date();
document
.writeln(‘Number of days in this month: ‘+d.daysInMonth());

And the result (live!):

31

Getting The Name Of The Day And Month


While the Javascript Date Object has many useful features, one glaring oversight is that when you ask it for the day or month it will return only the numerical representation. This is easy enough to fix with prototypes however.

Date.prototype.getDayName = function(shortName) {
   
var Days = [‘Sunday’, ‘Monday’, ‘Tuesday’, ‘Wednesday’, ‘Thursday’, ‘Friday’, ‘Saturday’];
   
if (shortName) {
     
return Days[this.getDay()].substr(0,3);
   
} else {
     
return Days[this.getDay()];
   
}
}

Date.prototype.getMonthName = function() {
   
return [‘January’, ‘February’, ‘March’, ‘April’, ‘May’, ‘June’, ‘July’, ‘August’, ‘September’, ‘October’, ‘November’, ‘December’][this.getMonth()];
}

These two methods are pretty simple to use. If you want the month name just do…

var d = new Date();
month
= d.getMonthName();

If you want the name of the day, do…

var d = new Date();
day
= d.getDayName();

If you’d like the three character day name (mon/tue/wed, etc) then pass an argument to getDayName. As long as the argument isn’t false, null or any other falsey value the name will be shortened to its three letter equivalent.

var d = new Date();
day
= d.getDayName(true);

Making a Calendar


Making a calendar is a bit more complex than making a timer or clock but mostly because any calendar script is going to be generating HTML to display the calendar and whenever you have programs writing programs things always get a bit funky! We’ll do this as a prototype so all you have to do is create a date with the month you want the calendar for and use the .calendar() method.

Note this prototype assumes you’ve included the getMonthName() and daysInMonth() prototypes described above, the calendar will break if they are not included in your code.

Date.prototype.getMonthName = function() {
   
return [‘January’, ‘February’, ‘March’, ‘April’, ‘May’, ‘June’, ‘July’, ‘August’, ‘September’, ‘October’, ‘November’, ‘December’][this.getMonth()];
}

Date.prototype.daysInMonth = function () {
   
return new Date(this.getFullYear(), this.getMonth()+1, 0).getDate()
}

Date.prototype.calendar = function() {

   
// The number of days in the month.
   
var numDays = this.daysInMonth();
   
// Get the starting day of this calendar, mon, tue, wed, etc.
   
var startDay= new Date(this.getFullYear(), this.getMonth(), 1).getDay();
   
   
// We’ll build our table in the buildStr variable then pass what we build back.
   
// This will be a HTML table — Build the header rows…
   
var buildStr =‘<table summary=”Calendar” class=”calendar” style=”text-align: center”>’;
   buildStr
+=‘<tr><td colspan=7>’+this.getMonthName()+‘ ‘+this.getFullYear()+‘</td></tr>’;
   buildStr
+=‘<tr><td>Sun</td><td>Mon</td><td>Tue</td>’;
   buildStr
+=‘<td>Wed</td><td>Thu</td><td>Fri</td>&

Open Webmail 安裝流程

Open Webmail 官方網站:http://openwebmail.org/
注意:要架設 Open Webmail 前,請務必先將 sendmail、dovecot 架設好


安裝


cd
yum -y install perl-suidperl perl-Compress-Zlib perl-Text-Iconv
wget http://openwebmail.org/openwebmail/download/redhat/rpm/release/openwebmail-2.52-1.i386.rpm
rpm -ivh openwebmail-2.52-1.i386.rpm
rm -rf openwebmail-2.52-1.i386.rpm
修改 openwebmail.conf


cp /var/www/cgi-bin/openwebmail/etc/openwebmail.conf /var/www/cgi-bin/openwebmail/etc/openwebmail.conf.bak
vi /var/www/cgi-bin/openwebmail/etc/openwebmail.conf
55行 enable_pop3 yes 修改成–> enable_pop3 no
62行 default_language en 修改成–> default_language zh_TW.Big5
85行 default_iconset Cool3D.English 修改成–> default_iconset Cool3D.Chinese.Traditional


 


76行 <default_signature>
77行 —
78行 Open WebMail Project (http://openwebmail.org)
79行 </default_signature>


#此此四行是使用者寄信的預設簽名檔,請自行修改紅字部分


 


202行 webdisk_rootpath /webdisk 修改成–> webdisk_rootpath /


修改 dbm.conf


cp /var/www/cgi-bin/openwebmail/etc/defaults/dbm.conf /var/www/cgi-bin/openwebmail/etc/defaults/dbm.conf.bak
vi /var/www/cgi-bin/openwebmail/etc/defaults/dbm.conf
dbm_ext .db
dbmopen_ext .db
dbmopen_haslock no


使用 Open WebMail 變更密碼的時候,順便修改 samba 密碼


cp /var/www/cgi-bin/openwebmail/etc/auth_unix.conf /var/www/cgi-bin/openwebmail/etc/auth_unix.conf.bak
vi /var/www/cgi-bin/openwebmail/etc/auth_unix.conf
13行 change_smbpasswd no 修改成–> change_smbpasswd yes


初始化


/var/www/cgi-bin/openwebmail/openwebmail-tool.pl –init
測試:https://IP/cgi-bin/openwebmail/openwebmail.pl
縮短 Open WebMail 連結網址:


vi /etc/httpd/conf/httpd.conf
ScriptAlias /mail “/var/www/cgi-bin/openwebmail/openwebmail.pl”


#在設定檔最後面加上這一行


/etc/rc.d/init.d/httpd restart
測試:https://IP/mail/
註:
參考資料:http://turtle.ee.ncku.edu.tw/~tung/openwebmail/
How to install Open WebMail on Fedora Core 3 By Thomas Chung <tchung AT openwebmail.org>
官方安裝說明檔:more /var/www/data/openwebmail/doc/readme.txt
cd /var/www/cgi-bin/openwebmail/etc/
openwebmail.conf – 主要的設定檔,管理者要設定的選項,應該都寫在這個檔案裡頭
openwebmail.conf.help – openwebmail.conf 所有選項的說明檔

分享一下我的Eclipse啓動參數

eclipse.exe -nl en_US -clean -vmargs -Xverify:none -XX:+UseParallelGC -XX:PermSize=20M -XX:MaxNewSize=32M -XX:NewSize=32M -Xmx256m -Xms128m


-nl 後面跟的是語言


-clean 是當啓動Eclipse IDE時清空緩衝,一般來説在没有更新插件的情况下,去掉這個參數啓動速度更快。


-vmargs 使用JRE的參數,後面就是JRE的參數了:


-Xverify:none 去掉JAR包數據驗證,一般來説只有在網絡環境下才需要驗證JAR包數據的有效性。本地的話可以不用驗證。


-XX:+UseParallelGC 使用并行垃圾收集機制,據説這個GC算法比較快。具體不清楚。


-XX:PermSize=20M -XX:MaxNewSize=32M -XX:NewSize=32M 這三個就是設置詳細的緩衝數據了。詳情看Java官方網站的介紹吧。


-Xmx256m Java虚擬機最大使用内存容量,根據你所使用機器的内容大小設置,只要不超過最大内存容量就好。


-Xms128m Java虚擬機初始化内存容量。


在偶Athlon64 3000+,1GB DDR400的機器第一次啓動速度不到20秒,第二次啓動速度10秒左右。希望對大家有用。