Saturday, October 5, 2013

Add Oracle driver to Maven

  1. Download driver ojdbc6.jar from oracle.
  2. Install driver to maven local repository with the following command.
  3. mvn install:install-file -Dfile={driver/path/ojdbc.jar} -DgroupId=com.oracle 
    -DartifactId=ojdbc6 -Dversion=11.2.0 -Dpackaging=jar
  4. Copy following to your pom.xml.
    <!-- Oracle DB driver -->
    <dependency>
     <groupId>com.oracle</groupId>
     <artifactId>ojdbc6</artifactId>
     <version>11.2.0</version>
    </dependency>
    

Monday, September 23, 2013

Remote Debugging with Eclipse + WebSphere 7

Enable WebSphere in Debug Mode

  1. Servers > Server Types > WebSphere application servers
  2. Under Server Infrastructure section > expand Java and Process Management > Process definition
  3. Under Additional Properties section > click Java Virtual Machine
  4. Checked the “Debug Mode”
  5. In Debug arguments textbox, put this

    -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8888
  6. Restart WebSphere server instance.


    Now, WebSphere is started in debug mode, and listening on port 8888. (Later, Eclipse will connect to this port for debugging)

To create archive

If you are using ant script

Compile your java classes with option debug="true" in your ant script.
"${compiled.directory}" fork="no" srcdir="./src/main" sourcepathref="src.classpath" debug="true" debuglevel="lines,vars,source">

If you are using eclipse
Before compilation check the option in eclipse for
Window  > Preferences > Java > Compiler > Classfile Generation:  "add line number attributes to generated class file" should be checked.
clean build all, recompile.

Install or deploy web application to WebSphere

“war” your web application, install (first-time) or deploy it to WebSphere. And start your web application in WebSphere.

Eclipse’s Java Debugger (jdb)

In Eclipse IDE, under your project source
  1. Click on “Run”, “Debug Configurations…”
  2. Select “Remote Java Application”, right click and select “New”
  3. Renamed a new name , e.g “WebSphere 7 Instance”
  4. In “Connection Type”, select default, “Standard (Socket Attached)
  5. Host, put your WebSphere host IP
  6. Port, put 8888.
  7. Click on the debug button.


Now, Eclipse debugger is started and connected to port 8888.

Debugging

Open your favorite browser, and type your web application URL. Now, Eclipse will stop at your predefined breakpoints.



Done.

Know/How

  1. Local eclipse can block the remote system to run, if it is not disconnected. So, if server is deploying/undeploying the application the all the machine should be disconnected from remote.
  2. It is always better to use IP address then the machine name in the configuration, because some time debug does not work while using machine name.

References: 

  1. http://www.mkyong.com/websphere/remote-debugging-with-eclipse-websphere-7/

Sunday, September 1, 2013

Restart Tomcat Service

Restart Tomcat Service with cleaned webapps directory

Create power-shell script file with below script (say "serviceRestarter.ps1")



# *******************************************************************************
# Use of this script is
# path_to_script_file ServiceName="" catalinaHome="" appName=""
# SERVICE_NAME is the name of the service to restart
# CATALINA_HOME is absolute path of catalina_home
# APP_NAME is the name of the war file without extension
#
# @author Amit Nema
#
# *******************************************************************************

#parameters to pass with script
param(
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$ServiceName,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$catalinaHome,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$appName
)

# type the name of the service in the quotes here
$service = Get-Service -Name $ServiceName

#Stoping Service
Stop-Service $ServiceName
$service.WaitForStatus('Stopped','00:10:00')
if ($service.Status -ne 'Stopped') { 
Write-Warning 'Something is fishy here...'
exit
} Else {
write-host 'Service ' $ServiceName ' is ' $service.Status ' now.'
}
sleep 10

#Delete the content of web-apps
write-host 'Removing application :' $catalinaHome'\webapps\'$appName '.'
Remove-Item -Recurse -Force $catalinaHome'\webapps\'$appName
Remove-Item -Force $catalinaHome'\webapps\'$appName'.war'
Remove-Item -Recurse -Force $catalinaHome'\work\Catalina\localhost\'$appName
Remove-Item -Recurse -Force $catalinaHome'\work\Catalina\localhost\_'
sleep 10

#Starting Service
Start-Service $ServiceName
$service.WaitForStatus('Running','00:10:00')
if ($service.Status -ne 'Running') { 
Write-Warning 'Something is fishy here...' 
} Else {
write-host 'Service ' $ServiceName ' is ' $service.Status ' now.'
}
sleep 10

Thursday, June 6, 2013

JDK as ZIP

Oracel do not provide JDK as zip, unfortunately.
However, you can:
  • Create working JDK directory ("C:\JDK" in this case)
  • Download latest version of JDK from oracle (for example "jdk-7u7-windows-i586.exe")
  • Download and install 7-zip or download 7-zip portable version if you are not administrator
  • With 7-zip extract all the files from "jdk-7u7-windows-i586.exe" in directory "C:\JDK"
  • In command shell (cmd.exe) do the following:
    • change directory to directory C:\JDK.rsrc\JAVA_CAB10
    • execute command: extrac32 111
  • Unpack C:\JDK\.rsrc\JAVA_CAB10\tools.zip with 7-zip
  • In command shell (cmd.exe) do the following:
    • change directory to C:\JDK.rsrc\JAVA_CAB10\tools\
    • execute command: for /r %x in (*.pack) do .\bin\unpack200 -r "%x" "%~dx%~px%~nx.jar" (this will convert all pack files into jar)
  • Copy whole directory and all subdir of c:\JDK.rsrc\JAVA_CAB10\tools" where you want your JDK to be and setup manually JAVA_HOME and PATH to point to your JDK dir and its BIN subdir.
Thats all. After this you'll be able at least to use javac.exe

Reference: http://stackoverflow.com/questions/1619662/where-can-i-get-the-latest-jre-jdk-as-a-zip-file-i-mean-no-exe-installer

Sunday, June 2, 2013

Maven ( POM ) Best Practices


  • Make the build reproducible
    • Always specify a version for Maven2 plugins
    • Minimize number of SNASPHOT dependencies
    • Use dependency management section
    • Beware of relocation in maven repo
    • After a dependency modification, double check the produced artifacts
  • Use and abuse of modules
    • more “technical/layered”
    • more business oriented
  • Make the build maintainable
    • Prefer default directory layout
    • Avoid duplication by moving common tags to parent pom
    • Always specify a version of dependencies in a parent pom
    • Use Properties Liberally
    • Minimize the number of Profiles
  • Make the build portable
    • Don’t commit eclipse and maven artifacts
    • Don't modify pom/artifactsin your "enterprise" repository

Additionally:
  • Make use of maven-resources-plugin. E.g. As below in pom.
<plugin>
<!-- http://maven.apache.org/plugins/maven-resources-plugin/ -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<delimiters>
<delimiter>@*@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
<nonFilteredFileExtensions> 
<nonFilteredFileExtension>xls</nonFilteredFileExtension> 
<nonFilteredFileExtension>xlsx</nonFilteredFileExtension> <nonFilteredFileExtension>pdf</nonFilteredFileExtension> 
</nonFilteredFileExtensions>
</configuration>
</plugin>

Monday, April 22, 2013

Identify Invalid Objects

The DBA_OBJECTS view can be used to identify invalid objects using the following query.
    SELECT owner,
           object_type,
           object_name,
           status
    FROM   dba_objects
    WHERE  status = 'INVALID' and owner='ownername'
    ORDER BY owner, object_type, object_name;

Monday, April 15, 2013

Log into Database

Log Table Structure:

CREATE TABLE LOGS
  (
    USER_ID   VARCHAR2(20 BYTE) ,
    DATED     TIMESTAMP(6) NOT NULL ,
    LOG_LEVEL VARCHAR2(10 BYTE) NOT NULL ,
    LOGGER    VARCHAR2(100 BYTE) NOT NULL ,
    METHOD    VARCHAR2(100 BYTE) NOT NULL ,
    LINE      NUMBER NOT NULL ,
    MESSAGE   VARCHAR2(1000 BYTE) NOT NULL
  );

Log4j Configuration File:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <appender name="jdbcAppender"
class="com.company.project.package.logger.Log4JJDBCAppender">
<!-- threshold fatal ensures only fatal (and above level if any) msgs only
will logged -->
<param name="threshold" value="FATAL" />
<!-- If you want the raw connection then uncoment this segment, otherwise datasource will be used
<param name="URL" value="jdbc:mysql://localhost/test" />
        <param name="user" value="root" />
        <param name="password" value="admin" />
        <param name="driver" value="com.mysql.jdbc.Driver" />
-->
<param name="dataSource" value="jdbc/ekp_refactor" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="INSERT INTO LOGS (USER_ID, DATED, LOG_LEVEL, LOGGER, METHOD, LINE, MESSAGE) VALUES('%X{username}','%d{dd MMM yyyy hh:mm:ss a}','%p','%C','%5M','%L','%m')" />
</layout>
<filter class="com.company.project.package.logger.DBLoggingFilter">
</filter>
</appender>

    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
              value="%d{ISO8601} %p (%C;%L) %m%n"
            />
        </layout>
    </appender>

    <logger name="company.com.package">
        <level value="debug"/>
        <appender-ref ref="jdbcAppender"/>
    </logger>

    <root>
        <level value="error"/>
        <appender-ref ref="STDOUT"/>
    </root>

</log4j:configuration>

Java Files for customization:

Log4JJDBCAppender.java

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.log4j.jdbc.JDBCAppender;
import org.apache.log4j.spi.ErrorCode;

/**
 *
 * JDBC Appender to get the connection to log messages into DB via Log4j. Extension of the log4j {@link JDBCAppender} to allow using a JNDI data source rather
 * than a direct connection.
 *
 *
 * Example configuration:
 *
 *
 * <appender name="database" class="com.company.project.package.Log4JJDBCAppender">
 * <param name="dataSource" value="java:comp/jdbc/datasource" />
 * <layout class="org.apache.log4j.PatternLayout">
 * <param name="ConversionPattern" value="INSERT INTO LOGS (USER_ID, DATED, LOG_LEVEL, LOGGER, METHOD, LINE, MESSAGE) 
 * VALUES('%X{username}','%d{dd MMM yyyy hh:mm:ss a}','%p','%C','%5M','%L','%m')" />
 * </layout>
 * </appender>
 * 

 *
 * @author Amit
 */
public class Log4JJDBCAppender extends JDBCAppender {

    private static final Pattern SQL_VALUE_PATTERN = Pattern.compile("'(.*?)'(?=\\s*[,)])", Pattern.MULTILINE);
    private String dataSource;

    /** {@inheritDoc} */
    @Override
    protected Connection getConnection() throws SQLException {
        if (getDataSource() == null) {
            return super.getConnection();
        } else {
            return lookupDataSource().getConnection();
        }
    }

    /**
     * Looks up the datasource in the naming context specified by the {@link #dataSource}.
     *
     * @return the datasource.
     */
    private DataSource lookupDataSource() {
        try {
            Context context = new InitialContext();
            return (DataSource)context.lookup(getDataSource());
        } catch (NamingException e) {
            throw new RuntimeException("Cannot find JNDI DataSource: " + getDataSource(), e);
        }
    }

    /** {@inheritDoc} */
    @Override
    protected void closeConnection(Connection con) {
        try {
            con.close();
        } catch (SQLException e) {
            errorHandler.error("Failed to close connection", e, ErrorCode.CLOSE_FAILURE);
        }
    }

    /**
     * Executes the specified SQL statement, by parsing its values and turning them into parameters, so that characters that must be escaped in a SQL statement
     * are supported.
     */
    @Override
    protected void execute(String sql) throws SQLException {
        String statement = sql;
        ArrayList args = new ArrayList();
        Matcher m = SQL_VALUE_PATTERN.matcher(sql);
        while (m.find()) {
            args.add(m.group(1));
            statement = statement.replace(m.group(), "?");
        }

        executeStatement(statement, args.toArray(new String[args.size()]));
    }

    /**
     * Executes the statement settings its parameters to the specified arguments.
     *
     * @param statement
     *            the statement to execute.
     * @param args
     *            the parameter values.
     */
    protected void executeStatement(String statement, String[] args) throws SQLException {
        Connection con = getConnection();
        PreparedStatement stmt = null;
        try {
            stmt = con.prepareStatement(statement);
            for (int i = 0; i < args.length; i++) {
                stmt.setString(i + 1, args[i]);
            }
            stmt.executeUpdate();
        } catch (SQLException e) {
            if (stmt != null) {
                stmt.close();
            }
            throw e;
        }
        stmt.close();
        closeConnection(con);
    }

    public void setDataSource(String dataSource) {
        this.dataSource = dataSource;
    }

    public String getDataSource() {
        return dataSource;
    }
}

DBLoggingFilter.java

import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;

/**
 *
 * This is Filter executes before entry of message into the database. Here, the
 * method to decide whether messages should me logged into the Database or Not.
 *
 * @author Amit
 *
 */
public class DBLoggingFilter extends Filter {

    @Override
    public int decide(LoggingEvent le) {

        Object loggingEnabledObject = le.getMDC("loggingEnabled");

        if (loggingEnabledObject == null) {
            return DENY;
        }

        boolean loggingEnabled = (Boolean)loggingEnabledObject;
        /*System.out.println("LOGGING " + (loggingEnabled ? "" : "NOT ")
                + "ALLOWED FOR USER: " + le.getMDC("username"));*/
        if (loggingEnabled) {
            return ACCEPT;
        } else {
            return DENY;
        }
    }
}

LoggerFilter.java

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.log4j.MDC;

import com.company.project.package.bean.User;

/**
 *
 * Filter for the logger, which sets the required information used to log
 * messages into the database..
 *
 * @author Amit
 *
 */
public class LoggerFilter implements Filter {

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpSession session = ((HttpServletRequest)request).getSession(false);
        if (session != null) {
            Object object = session.getAttribute("USER");
            if (object instanceof User) {
                User user = (User)object;

                if (user != null) {
                    String username = user.getUsername() != null ? user
                            .getUsername() : "";
                    MDC.put("username", username);
                    MDC.put("loggingEnabled", true);
                }
            }
        }
        chain.doFilter(request, response);

        MDC.remove("username");
        MDC.remove("loggingEnabled");
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }
}

Note: LoggerFilter is a normal servlet, could be placed inside web.xml or spring-applicationSecurity.xml.

Monday, February 25, 2013

How to connect SQLPlus without tnsnames.ora

Open RUN (window + R) and copy the following command (replacing database properties)
sqlplus user/pwd@"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=hostName)(Port=portNumber))(CONNECT_DATA=(SID=systemId)))"