Thursday, February 16, 2012

SQL Server Checklist for DBA



Daily Checklist

  • Backups - Check your backups to validate that they were successfully created per your process.
    • MSSQLTips.com Category: Backup and Recovery
  • Nightly Processing - Review the nightly or early morning processes.
  • SQL Server Error Log - Review the SQL Server error log for any errors or security issues (successful or failed logins) that are unexpected.
    • SQL Server 2005 Exposed - Log File Viewer
  • Windows Event Log - Review the Application Event Log at a minimum to find out if any Windows or hardware related errors or warnings are being written.
    • Some of the hardware vendors write warnings to the Windows Event Log when they anticipate an error is going to occur, so this gives you the opportunity to be proactive and correct the problem during a scheduled down time, rather than having a mid day emergency.
    • SQL Server 2005 Exposed - Log File Viewer
  • SQL Server Agent Jobs - Review for failed SQL Server Agent Jobs.
    • Finding SQL Server Agent Job Failures
  • HA or DR Logs - Check your high availability and/or disaster recovery process logs.  Depending on the solution (Log Shipping, Clustering, Replication, Database Mirroring, CDP, etc.) that you are using dictates what needs to be checked.
  • Performance Logs - Review the performance metrics to determine if your baseline was exceeded or if you had slow points during the day that need to be reviewed.
    • MSSQLTips.com Category: Performance Tuning
  • Security Logs - Review the security logs from a third party solution or from the SQL Server Error Logs to determine if you had a breach or a violation in one of your policies.
  • Centralized error handling - If you have an application, per SQL Server or enterprise level logging, then review those logs for any unexpected errors.
    • Standardized Error Handling and Centralized Logging
  • Storage - Validate you have sufficient storage on your drives to support your databases, backups, batch processes, etc. in the short term.
  • Service Broker - Check the transmission and user defined queues to make sure data is properly being processed in your applications.
    • MSSQLTips.com Category: Service Broker
  • Corrective Actions - Take corrective actions based on the issues and/or errors that you found.
  • Improvements - Look for opportunities to improve your environment based on the review and analysis you have performed.
  • Learn something new - Although this review and correction process could be time consuming, take some time every day to learn something new to improve your knowledge of the technology you work on every day.

Weekly or Monthly Checklist

  • Backup Verification (Comprehensive)- Verify your backups and test on a regular basis to ensure the overall process works as expected.  What is meant by this is to:
    • Contact your off site tape vendor to obtain a tape
    • Validate that the tape goes to the correct office
    • Validate that the vendor delivers the correct tape
    • Validate that the vendor delivers the tape in the correct time period
    • Validate that the software version you use to perform the restore is compatible with the version from the tape
    • Validate that the tape does not have any restore errors
    • Validate that sufficient storage is available to move the backup to the needed SQL Server
    • Validate that the SQL Server versions are compatible to restore the database
    • Validate that no error messages are generated during the restore process
    • Validate that the database is accurately restored and the application will function properly
  • Backup Verification (Simple) - Verify your backups on a regular basis.
    • Maintenance Tasks: Automating the RESTORE VERIFYONLY Process
    • Verifying Backups with the RESTORE VERIFYONLY Statement
  • Windows, SQL Server or Application Updates - Check for service packs/patches that need to be installed on your SQL Server from either a hardware, OS, DBMS or application perspective
    • MSSQLTips.com Category: Service Packs / Patches
  • Capacity Planning - Perform capacity planning to ensure you will have sufficient storage for a specific period of time such as for 6, 12 or 18 months.
    • Easing the Capacity Planning Burden
  • Fragmentation - Review the fragmentation for your databases to determine if you particular indexes must be rebuilt based on analysis from a backup SQL Server.
    • MSSQLTips.com Category: Fragmentation
  • Maintenance - Perform database maintenance on a weekly or monthly basis.
    • MSSQLTips.com Category: Maintenance
  • Security - Remove unneeded logins and users for individuals that have left the organization, had a change in position, etc.
  • Shrink databases - If databases or transaction logs are larger, than necessary shrink those files to free up disk space.
    • SQL Server 2000 to 2005 Crosswalk - Database Maintenance Plan Wizard to SQL Server Integration Services (SSIS)

Opportunities for Automation

  • Setup alerts for specific error levels or error messages that impact your SQL Servers in order to be notified automatically.
    • Database Backup and Restore Failure Notifications
  • Setup Jobs to query for specific conditions in your tables to validate data was loaded or data is being added to specific tables based on your business processes throughout the day.
  • Setup notification on Job success, failure or completion.
    • One word of warning is to check your business critical Jobs on a regular basis just to be sure they are working properly.  Nothing is worse than finding out a key process has been failing for days, weeks or months and the reason notifications have not been sent are due to an incorrect configuration, full mailbox, etc.  It may be 30 minutes on a weekly basis that is time well spent.
  • Setup centralized error handling on a per SQL Server, application or enterprise basis then determine the business rules for specific error conditions.


Monday, February 13, 2012

Deterministic and Nondeterministic Functions



Deterministic functions always return the same result any time they are called with a specific set of input values and given the same state of the database. Nondeterministic functions may return different results each time they are called with a specific set of input values even if the database state that they access remains the same.

All functions are deterministic or nondeterministic:

  • Deterministic functions always return the same result any time they are called with a specific set of input values.

  • Nondeterministic functions may return different results each time they are called with a specific set of input values.

Whether a function is deterministic or nondeterministic is called the determinism of the function.

For example, the DATEADD built-in function is deterministic because it always returns the same result for any given set of argument values for its three parameters. GETDATE is not deterministic because it is always invoked with the same argument, yet the value it returns changes each time it is executed.

Earlier versions of Microsoft® SQL Server™ have no functionality that is dependent on the determinism of functions. In Microsoft SQL Server 2000, nondeterministic functions cannot be specified in two types of Transact-SQL expressions:

  • An index cannot be created on a computed column if the computed_column_expression references any nondeterministic functions.

  • A clustered index cannot be created on a view if the view references any nondeterministic functions.

One of the properties SQL Server records for user-defined functions is whether the function is deterministic. A nondeterministic user-defined function cannot be invoked by either a view or computed column if you want to create an index on the view or computed column.

User-Defined Function Determinism

Whether a user-defined function is deterministic or nondeterministic depends on how the function is coded. User-defined functions are deterministic if:

  • The function is schema-bound.

  • All built-in or user-defined functions called by the user-defined function are deterministic.

  • The body of the function references no database objects outside the scope of the function. For example, a deterministic function cannot reference tables other than table variables that are local to the function.

  • The function does not call any extended stored procedures.

User-defined functions that do not meet these criteria are marked as nondeterministic. Built-in nondeterministic functions are not allowed in the body of user-defined functions.

Built-in Function Determinism

You cannot influence the determinism of any built-in function. Each built-in function is deterministic or nondeterministic based on how the function is implemented by Microsoft SQL Server.



There are three ways to retrieve the current datetime in SQL SERVER.
CURRENT_TIMESTAMP, GETDATE(), {fn NOW()}

CURRENT_TIMESTAMP
CURRENT_TIMESTAMP is a nondeterministic function. Views and expressions that reference this column cannot be indexed. CURRENT_TIMESTAMP can be used to print the current date and time every time that the report is produced.

GETDATE()
GETDATE is a nondeterministic function. Views and expressions that reference this column cannot be indexed. GETDATE can be used to print the current date and time every time that the report is produced.

{fn Now()}
The {fn Now()} is an ODBC canonical function which can be used in T-SQL since the OLE DB provider for SQL Server supports them. {fn Now()} can be used to print the current date and time every time that the report is produced.

If you run following script in Query Analyzer. I will give you same results. If you see execution plan there is no performance difference. It is same for all the three select statement.
SELECT CURRENT_TIMESTAMP
GO
SELECT {fn NOW()}
GO
SELECT GETDATE()
GO

Performance:
There is absolutely no difference in using any of them. As they are absolutely same.

My Preference:
I like GETDATE(). Why? Why bother when they are same!!!



Thursday, February 9, 2012

SQL Server Agent Job Management Scripts



Solution

Since we will probably be dealing with existing jobs, these are the basic changes we want to implement:

  • Naming conventions for scheduled jobs
  • Naming conventions for job steps
  • Adding Job Categories
  • Adding Job Descriptions

With the help of several targeted scripts, we can work on a test server to implement the following steps to get a suitable set of scripts.

  1. Create sample jobs and steps
  2. Execute Jobs to verify the functionality
  3. Generate and execute code for job names modification, job categories and job description
  4. Generate and execute code for job steps name modification
  5. Test functionality with changes made

When performing the task on a production server steps 1 and 2 would be skipped. Also, if you have some scheduled jobs already present on the test server that you can work with, then steps 1 and 2 may be skipped as well.


Create Sample Jobs and Steps

For simplicity, we will create a few jobs without a schedule. The job steps only have a SELECT statement to execute. The following script will create the jobs and add to the server. You may create as many jobs as you want by just replacing job names at the required places in the below script. I will create three jobs named Job1, Job2 and Job3.

--Script #1: Create sample jobs and steps on server

USE msdb
GO

-- Create Job
EXEC dbo.sp_add_job @job_name = N'Job1'
GO

-- Create Job Step1 and Step2
EXEC sp_add_jobstep
@job_name = N'Job1',
@step_name = N'Step1',
@on_success_action= 3,
@command = 'select ''Job step completed'''

EXEC sp_add_jobstep
@job_name = N'Job1',
@step_name = N'Step2',
@on_success_action= 1,
@command = 'select ''Job step completed'''
GO

-- Add job to Server
EXEC dbo.sp_add_jobserver
@job_name = N'Job1',
@server_name = N'Provide Server name here'
GO

I have created three jobs Job1, Job2 and Job3 with 2 steps in each. No schedule has been configured and jobs would need to be executed manually. After creating the jobs and steps, we may verify using SSMS or the following script.

--Script #2: Verify the created jobs and steps

USE [msdb]
GO

SELECT name, step_name
FROM dbo.sysjobs INNER JOIN dbo.sysjobsteps
ON dbo.sysjobs.job_id = dbo.sysjobsteps.job_id
GO


Execute Jobs to Verify Functionality

It would be good to execute and test the sample jobs. We may use SSMS or the following T-SQL for execution of the created jobs. I have used the following T-SQL commands for execution of the three jobs

--Script #3: Execute Jobs

USE [msdb]
GO

EXEC dbo.sp_start_job @job_name = 'Job1'
EXEC dbo.sp_start_job @job_name = 'Job2'
EXEC dbo.sp_start_job @job_name = 'Job3'
GO

You can also verify the execution through the following script.

--Script #4: verify the successful execution

USE [msdb]
GO

SELECT j.name JobName,h.step_name StepName,
STUFF(STUFF(RIGHT('000000' + CAST ( h.run_time AS VARCHAR(6 ) ) ,6),5,0,':'),3,0,':') RunTime,
case h.run_status when 0 then 'failed'
when 1 then 'Succeded'
when 2 then 'Retry'
when 3 then 'Cancelled'
when 4 then 'In Progress'
end as ExecutionStatus
FROM sysjobhistory h inner join sysjobs j
ON j.job_id = h.job_id AND step_name <> '(Job outcome)'
ORDER BY runtime DESC, j.name
GO

Generate and Execute Code for Job Name Modification, Job Category and Job Description

Now we can try our modification scripts on the created jobs. First, we will generate code for changing job steps using a system stored procedure.

--Script #5: Generate commands to change job names

USE msdb
GO

SELECT 'EXEC dbo.sp_update_job
@job_name = '''+name+''',
@new_name = ''New Name Here'',
@description = ''Description Here'',
@category_name = ''Description Here'''
FROM sysjobs
GO

As a result from runing the above commands, statements will be generated for changing the name, adding a job description and categories as shown in script #6 below. Paste these commands in a SSMS query pane and take time to analyze and provide meaningful names, descriptions and categories.

It is important to note that SQL Server allows only predefined categories to be used. Read this tip to learn more about Job Categories and also how to add your own categories. By following the steps mentioned in the tip, I have created a new category "MSSQLTips sample jobs" to be used. If you already have a suitable predefined category then it may be used here.

--Script #6: Provide parameters and execute statements

EXEC dbo.sp_update_job @job_name = 'Job1', @new_name = 'Sample Job 1', @description = 'Created for MSSQL tip', @category_name = 'MSSQLTips sample jobs'

EXEC dbo.sp_update_job @job_name = 'Job2', @new_name = 'Sample Job 2', @description = 'Created for MSSQL tip', @category_name = 'MSSQLTips sample jobs'

EXEC dbo.sp_update_job @job_name = 'Job3', @new_name = 'Sample Job 3', @description = 'Created for MSSQL tip', @category_name = 'MSSQLTips sample jobs'
GO

To confirm the changes run sp_help_job system stored procedure in MSDB database. Below I can see the changes were made.

 confirm the changes by running sp_help_job system stored procedure in MSDB database


Generate and Execute Code for Job Step Name Modification

Now we can move to changing job step names. SQL Server provides no system stored procedure for this purpose. Hence we will create our own stored procedure for this purpose. This procedure takes three parameters Job Name, Current Step Name and New Step Name.

Script #7: Generate commands for step name change

USE msdb
GO

CREATE PROCEDURE USP_UpdateJobSteps
(@JobName varchar(256), @StepName varchar(256), @NewName varchar(256))
AS
update dbo.sysjobsteps
set step_name = @NewName
FROM dbo.sysjobsteps INNER JOIN dbo.sysjobs
ON dbo.sysjobsteps.job_id = dbo.sysjobs.job_id
where step_name = @StepName
and dbo.sysjobs.name = @JobName
GO

If we want to generate the commands to change the job step names to be consistent we can execute the following code or use a WHERE clause to limit the jobs we want to change. This then creates the output that can be used in Script #9.

--Script #8: Generate commands for steps name change

USE msdb
GO

SELECT 'EXEC USP_UpdateJobSteps '''+name+' '', '''+step_name+''', ''Provide New Name Here'''
FROM dbo.sysjobs INNER JOIN dbo.sysjobsteps
ON dbo.sysjobs.job_id = dbo.sysjobsteps.job_id

The above command generated this script with job names, old step names and we can provide anew step name as follows:

--Script #9: Update job step names

USE msdb
GO

EXEC USP_UpdateJobSteps 'Sample Job 1 ', 'Step1', 'Step 1 of Sample Job 1'
EXEC USP_UpdateJobSteps 'Sample Job 1 ', 'Step2', 'Step 2 of Sample Job 1'
EXEC USP_UpdateJobSteps 'Sample Job 2 ', 'Step1', 'Step 1 of Sample Job 2'
EXEC USP_UpdateJobSteps 'Sample Job 2 ', 'Step2', 'Step 2 of Sample Job 2'
EXEC USP_UpdateJobSteps 'Sample Job 3 ', 'Step1', 'Step 1 of Sample Job 3'
EXEC USP_UpdateJobSteps 'Sample Job 3 ', 'Step2', 'Step 2 of Sample Job 3'
GO


Test and cleanup

Required changes are now implemented on Jobs and Steps. This can be verified by using script #2. Now we may test the functionality of jobs to make sure that modifications have made no impact on functionality of the jobs. Use script #3 (do not forget to provide updated job names) and script #4 to execute jobs and verify output respectively.

At this point if we want to drop the created stored procedure we can do this by using the drop command (DROP PROCEDURE USP_UpdateJobSteps).



SQL SERVER – Start Stop Restart SQL Server From Command Prompt


Click Start >> Run >> type cmd to start command prompt.

Start default instance of SQL Server
net start mssqlserver

Stop default instance of SQL Server
net stop mssqlserver

Start and Stop default instance of SQL Server.
You can create batch file to execute both the commands together.




Wednesday, February 8, 2012

SQL Server : Calender Functions e.g. First Day of Last Month



First Day of Month

select DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)
 

First Day of Last Month

select DATEADD(mm, DATEDIFF(mm,0,DATEADD(mm,-1,getdate())), 0)
 

Monday of the Current Week

select DATEADD(wk, DATEDIFF(wk,0,getdate()), 0)
 

Sudday of the Current Week

set DATEFIRST 1  select DATEADD(dd, 1 - DATEPART(dw, getdate()), getdate())
 

First Day of the Year

select DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)
 

First Day of the Quarter

select DATEADD(qq, DATEDIFF(qq,0,getdate()), 0)
 

Midnight for the Current Day

select DATEADD(dd, DATEDIFF(dd,0,getdate()), 0)
 

Last Day of Prior Month

select dateadd(ms,-3,DATEADD(mm, DATEDIFF(mm,0,getdate()  ), 0))
 

Last Day of Prior Year

select dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate()  ), 0))
 

Last Day of Current Month

select dateadd(ms,-3,DATEADD(mm, DATEDIFF(m,0,getdate()  )+1, 0))
 

Last Day of Current Year

select dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate()  )+1, 0))
 

First Monday of the Month

select DATEADD(wk, DATEDIFF(wk,0, dateadd(dd,6-datepart(day,getdate()),getdate()) ), 0)      



Friday, February 3, 2012

Creating Struts application in Eclipse


In this tutorial we will create a hello world Struts application in Eclipse editor. First let us see what are the tools required to create our hello world Struts application.
  1. JDK 1.5 above (download)
  2. Tomcat 5.x above or any other container (Glassfish, JBoss, Websphere, Weblogic etc) (download)
  3. Eclipse 3.2.x above (download)
  4. Apache Struts JAR files:(download). Following are the list of JAR files required for this application.
    • struts.jar
    • common-logging.jar
    • common-beanutils.jar
    • common-collections.jar
    • common-digester.jar

We will implement a web application using Struts framework which will have a login screen. Once the user is authenticated, (s)he will be redirected to a welcome page.

Let us start with our first struts based web application.

Open Eclipse and goto File -> New -> Project and select Dynamic Web Project in the New Project wizard screen.

After selecting Dynamic Web Project, press Next.

Write the name of the project. For example StrutsHelloWorld. Once this is done, select the target runtime environment (e.g. Apache Tomcat v6.0). This is to run the project inside Eclipse environment. After this press Finish.

Once the project is created, you can see its structure in Project Explorer.

Now copy all the required JAR files in WebContent -> WEB-INF -> lib folder. Create this folder if it does not exists.

Next step is to create a servlet entry in web.xml which points to org.apache.struts.action.ActionServlet class of struts framework. Open web.xml file which is there under WEB-INF folder and copy paste following code.


01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<servlet>
        <servlet-name>action</servlet-name>
        <servlet-class>
            org.apache.struts.action.ActionServlet
        </servlet-class>
        <init-param>
            <param-name>config</param-name>
            <param-value>/WEB-INF/struts-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

Here we have mapped url *.do with the ActionServlet, hence all the requests from *.do url will be routed to ActionServlet; which will handle the flow of Struts after that.

We will create package strutcures for your project source. Here we will create two packages, one for Action classes (net.viralpatel.struts.helloworld.action) and other for Form  beans(net.viralpatel.struts.helloworld.action).

Also create a class LoginForm in net.viralpatel.struts.helloworld.action with following content.


01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package net.viralpatel.struts.helloworld.form;
 
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
 
public class LoginForm extends ActionForm {
 
    private String userName;
    private String password;
 
    public ActionErrors validate(ActionMapping mapping,
            HttpServletRequest request) {
 
        ActionErrors actionErrors = new ActionErrors();
 
        if(userName == null || userName.trim().equals("")) {
            actionErrors.add("userName", new ActionMessage("error.username"));
        }
        try {
        if(password == null || password.trim().equals("")) {
            actionErrors.add("password", new ActionMessage("error.password"));
        }
        }catch(Exception e) {
            e.printStackTrace();
        }
        return actionErrors ;
    }
 
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

LoginForm is a bean class which extends ActionForm class of struts framework. This class will have the string properties like userName and password and their getter and setter methods. This class will act as a bean and will help in carrying values too and fro from JSP to Action class.
Let us create an Action class that will handle the request and will process the authentication. Create a class named LoginAction in net.viralpatel.struts.helloworld.action package. Copy paste following code in LoginAction class.


01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package net.viralpatel.struts.helloworld.action;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import net.viralpatel.struts.helloworld.form.LoginForm;
 
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 LoginAction extends Action {
 
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
 
        String target = null;
        LoginForm loginForm = (LoginForm)form;
 
        if(loginForm.getUserName().equals("admin")
                && loginForm.getPassword().equals("admin123")) {
            target = "success";
            request.setAttribute("message", loginForm.getPassword());
        }
        else {
            target = "failure";
        }
 
        return mapping.findForward(target);
    }
}

In action class, we have a method called execute() which will be called by struts framework when this action will gets called. The parameter passed to this method are ActionMapping, ActionForm, HttpServletRequest and HttpServletResponse. In execute() method we check if username equals admin and password is equal to admin123, user will be redirected to Welcome page. If username and password are not proper, then user will be redirected to login page again.

We will use the internationalization (i18n) support of struts to display text on our pages. Hence we will create a MessagesResources properties file which will contain all our text data. Create a folder resource under src (Right click on src and select New -> Source Folder). Now create a text file called MessageResource.properties under resources folder.

Copy the following content in your Upadate:struts-config.xml MessageResource.properties file.


1
2
3
4
5
label.username = Login Detail
label.password = Password
label.welcome = Welcome
 
error.username =Username is not entered.

Create two JSP files, index.jsp and welcome.jsp with the following content in your WebContent folder.

index.jsp

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<%@taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
<%@taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>
 
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Login page | Hello World Struts application in Eclipse</title>
    </head>
    <body>
    <h1>Login</h1>
    <html:form action="login">
         <bean:message key="label.username" />
         <html:text property="userName"></html:text>
         <html:errors property="userName" />
         <br/>
         <bean:message key="label.password"/>
        <html:password property="password"></html:password>
         <html:errors property="password"/>
        <html:submit/>
        <html:reset/>
    </html:form>
    </body>
</html>

welcome.jsp


01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Welcome page | Hello World Struts application in Eclipse</title>
    </head>
    <body>
    <%
        String message = (String)request.getAttribute("message");
    %>
        <h1>Welcome <%= message %></h1>
 
    </body>
</html>

Now create a file called struts-config.xml in WEB-INF folder. Also note that in web.xml file we have passed an argument with name config to ActionServlet class with value /WEB-INF/struts-config.xml.

Following will be the content of struts-config.xml file:


01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="ISO-8859-1" ?>
 
<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
 
<struts-config>
    <form-beans>
        <form-bean name="LoginForm"
            type="net.viralpatel.struts.helloworld.form.LoginForm" />
    </form-beans>
 
    <global-exceptions>
    </global-exceptions>
    <global-forwards></global-forwards>
 
    <action-mappings>
        <action path="/login" name="LoginForm" validate="true" input="/index.jsp"
            type="net.viralpatel.struts.helloworld.action.LoginAction">
            <forward name="success" path="/welcome.jsp" />
            <forward name="failure" path="/index.jsp" />
        </action>
    </action-mappings>
 
    <message-resources parameter="resource.MessageResource"></message-resources>
 
</struts-config>


And, that's it :) .. We are done with our application and now its turn to run it. I hope you have already configured Tomcat in eclipse. If not then:

Open Server view from Windows -> Show View -> Server. Right click in this view and select New -> Server and add your server details.
To run the project, right click on Project name from Project Explorer and select Run as -> Run on Server (Shortcut: Alt+Shift+X, R)

Login Page

Welcome Page