August 28, 2012

[Core Java] Using Regular Expression to extract anchor from html


String htmlLine = "What We Know Aboutâ¦Health Literacy?   [PDF-2.54MB]
"; htmlLine += "What We Know Aboutâ¦Health Literacy?   [PDF-2.54MB]
"; htmlLine += "What We Know Aboutâ¦Health Literacy?   [PDF-2.54MB]
"; htmlLine += "What We Know Aboutâ¦Health Literacy?   [PDF-2.54MB]
"; String expr ="]*)>" // Element Detail - Group1 + "([^<]+)" // Element Data - Group2 + ""; Pattern patt = Pattern.compile(expr, Pattern.DOTALL | Pattern.UNIX_LINES); Matcher m = patt.matcher(htmlLine); List anchors =new ArrayList(); while(m.find()) { anchors.add(""+m.group(2)+""); } //get external Links String hrefExpr = "href=\"" + "([^\"]+)" + "\"[^>]*>" + "([^<]+)"; patt = Pattern.compile(hrefExpr, Pattern.DOTALL | Pattern.UNIX_LINES); for(String anchor : anchors){ if(anchor.contains("href") || anchor.contains("HREF")){ m = patt.matcher(anchor); while(m.find()) { String href = m.group(1); if(!href.contains(".gov") && !href.contains("localhost")){ System.out.println(anchor); } } } }

July 19, 2012

[Log4J] Enable SQL logging for Hibernate

Step1. log4j.Properties [Add below entries in your log4j properties file]
### log just the SQL
log4j.logger.org.hibernate.SQL=trace
log4j.logger.org.hibernate.engine.query=trace
log4j.logger.org.hibernate.type=trace

### log JDBC bind parameters ###
log4j.logger.org.hibernate.jdbc=trace
#log4j.additivity.org.hibernate.SQL=false
log4j.logger.org.hibernate=info
### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=info
### log cache activity ###
log4j.logger.org.hibernate.cache=info
Step2: Set show_sql= true in hibernate-config.xml



 
  
  com.microsoft.sqlserver.jdbc.SQLServerDriver
  jdbc:sqlserver://localhost:1433
  ADMIN
  Admin1234
  validate

  
  1


  
  org.hibernate.dialect.SQLServerDialect


  
  thread
  
  org.hibernate.cache.NoCacheProvider
  
  true
  
 

[Spring 3.1] Method execution time logging using Spring AOP

Step 1. configure 'applicationContext.xml'



<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.1.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util-3.1.xsd"
default-autowire="no">


<aop:aspectj-autoproxy />


<context:component-scan base-package="com.core" />


<bean id="businessProfiler" class="com.core.common.MethodLogger" />


</beans>


Step2: Provide Spring Dependency.




<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>




Step3 : Create MethodLogger.java



package com.core.common;


import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;


@Component
@Aspect
public class MethodLogger
{


private static final Logger log = Logger.getLogger("app." + MethodLogger.class.getName());


@Pointcut("execution(* com..*.*(..))")
public void businessMethods()
{
}


@Around("businessMethods()")
public Object timeMethod(ProceedingJoinPoint joinPoint) throws Throwable
{
long startTime = System.currentTimeMillis();
// stopWatch.start();


Object retVal = joinPoint.proceed();
long endTime = System.currentTimeMillis();


// stopWatch.stop();


// TODO: Optimize this junk code
StringBuffer logMessage = new StringBuffer();
logMessage.append(joinPoint.getTarget().getClass().getName());
logMessage.append(".");
logMessage.append(joinPoint.getSignature().getName());
logMessage.append("(");
// append args
Object[] args = joinPoint.getArgs();
for(int i = 0; i < args.length; i++)
{
logMessage.append(args[i]).append(",");
}
if(args.length > 0)
{
logMessage.deleteCharAt(logMessage.length() - 1);
}


logMessage.append(") execution time: " + (endTime - startTime) + " ms");
log.info(logMessage.toString());
return retVal;
}


/*
* @AfterReturning(pointcut = "execution(* com.core.common..*.*(..))",
* returning = "retVal") public void logAfterMethod(JoinPoint joinPoint,
* Object retVal) { }
*/
}


[log4j] Using DailyRollingFileAppender ,FileAppender and ConsoleAppender


log4j.properties



log4j.rootLogger=DEBUG, default,stdout


#log4j.appender.default=org.apache.log4j.FileAppender 
log4j.appender.default=org.apache.log4j.DailyRollingFileAppender
log4j.appender.default.file=log/default.log 
log4j.appender.default.Threshold=ALL 
log4j.appender.default.file.MaxFileSize=1MB
log4j.appender.default.file.MaxBackupIndex=7
log4j.appender.default.ImmediateFlush=true 
log4j.appender.default.layout=org.apache.log4j.PatternLayout 
log4j.appender.default.layout.ConversionPattern=%d %-5p %C.%M(%L)===>%m %n
log4j.appender.default.append=true 


#log4j.logger.app=ALL, app
#log4j.additivity.app=false
#log4j.appender.app=org.apache.log4j.FileAppender
#log4j.appender.app.file=logs/application.log 
#log4j.appender.app.Threshold=ALL 
#log4j.appender.app.ImmediateFlush=true 
#log4j.appender.app.layout=org.apache.log4j.PatternLayout 
#log4j.appender.app.layout.ConversionPattern=%d %-5p %C.%M(%L)===>%m%n
#log4j.appender.app.append=false 




### log just the SQL
log4j.logger.org.hibernate.SQL=trace


log4j.logger.org.hibernate.engine.query=trace


log4j.logger.org.hibernate.type=trace


### log JDBC bind parameters ###
log4j.logger.org.hibernate.jdbc=trace


#log4j.additivity.org.hibernate.SQL=false


log4j.logger.org.hibernate=info


#log4j.logger.org.hibernate.type=info


### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=info


### log cache activity ###
log4j.logger.org.hibernate.cache=info






# Direct log messages to a log file
log4j.logger.app=ALL, app
log4j.additivity.app=false
log4j.appender.app=org.apache.log4j.DailyRollingFileAppender
log4j.appender.app.file=log/application.log
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=7
log4j.appender.app.layout=org.apache.log4j.PatternLayout
log4j.appender.app.layout.ConversionPattern=%d{ABSOLUTE} %-5p %C.%M(%L)===>%m%n
log4j.appender.app.append=true 


# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=ALL
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE}  %-5p %C.%M(%L)===>%m%n


#log4j.logger.as.moes=debug
#
#log4j.logger.org.codehaus.groovy=warn
#log4j.logger.org.springframework=warn
#log4j.logger.grails=warn
#log4j.logger.grails.util.GrailsUtil=warn
#log4j.logger.org.hibernate=warn

[Log4J] DailyRollingFileAppender and RollingFileAppender

log4j.properties



# Root logger option

log4j.rootLogger=DEBUG, default,stdout





log4j.appender.default=org.apache.log4j.DailyRollingFileAppender

log4j.appender.default.file=log/default.log 
log4j.appender.default.Threshold=ALL 
log4j.appender.default.file.MaxFileSize=1MB
log4j.appender.default.file.MaxBackupIndex=7
log4j.appender.default.ImmediateFlush=true 
log4j.appender.default.layout=org.apache.log4j.PatternLayout 
log4j.appender.default.layout.ConversionPattern=%d %-5p %C.%M(%L)===>%m %n
log4j.appender.default.append=true 



# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=${catalina.base}/logs/application.log
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n


# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n


log4j.logger.as.moes=debug


log4j.logger.org.codehaus.groovy=warn
log4j.logger.org.springframework=warn
log4j.logger.grails=warn
log4j.logger.grails.util.GrailsUtil=warn
log4j.logger.org.hibernate=warn


log4j.xml



<xml version="1.0" encoding="UTF-8" ?>
<DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-4r [%t] %-5p %c %x - %m%n" />
        </layout>
    </appender>
    <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="file" value="${catalina.home}/logs/rejseportal.log" />
        <param name="DatePattern" value="'.'yyyy-MM-dd" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%t] %d{HH:mm:ss,SSS} %-5p %l - %m%n" />
        </layout>
    </appender>
    
    <logger name="as.moes">
        <level value="DEBUG" />
        <appender-ref ref="FILE" />
    </logger>
    <logger name="org.codehaus.groovy">
        <level value="WARN" />
        <appender-ref ref="FILE" />
    </logger>
    <logger name="org.springframework">
        <level value="WARN" />
        <appender-ref ref="FILE" />
    </logger>
    <logger name="grails.util.GrailsUtil">
        <level value="WARN" />
        <appender-ref ref="FILE" />
    </logger>
    <logger name="grails">
        <level value="WARN" />
        <appender-ref ref="FILE" />
    </logger>
    <logger name="org.hibernate">
        <level value="WARN" />
        <appender-ref ref="FILE" />
    </logger>
    <logger name="waffle">
        <level value="WARN" />
        <appender-ref ref="FILE" />
    </logger>


</log4j:configuration>

July 18, 2012

[Liferay] Load Balancing != Clustering


Just a quick post on a couple of misunderstandings I've seen out in the field lately... Simply setting up Liferay Portal to be load balanced does not mean it is clustered. 

First, let's be clear on what "load balancing" is. Load balancing is simply a technique to distribute workload across resources. It is but one component in a high-availability cluster. In Liferay's case, we are load balancing the volume of requests across multiple app servers, which may or may not be on physically separate hardware. Initially, this may seem sufficient, until you realize some of the components that the portal uses.

Clustering is not just pointing a load balancer to two (or more) Liferay nodes. You're not done. Why? Because there are certain components that need to be either centrally managed or synchronized. Here is the basic check list of components that need to be addressed in a Liferay cluster:


  • Load Balancer - it can be software (i.e. - Apache), or hardware (F5), or whatever you wish, really. All it is doing is redirecting requests. 
  • Centralized Database - Hopefully, you have gotten off of HSQL and are using a real DB server. This is a JBDC connection. It is abstracted from Liferay's point of view. Any level of redundancy you have behind that JDBC connection is up to you and your DBA. Just as an example, you may choose to configure a MySQL cluster, or Oracle RAC, for DB high availability
  • Ehcache - This is what Liferay uses out-of-the-box for it's Hibernate level 2 cache. This needs to be configured to sync, else you will see inconsistencies depending on what node the load balancer redirects end users to. You are not forced to use Ehcache, it is simply what it ships with. You could use something like Terracotta, for example. If you do not do this, you will most definitely see inconsistencies depending on the node the end user is on, due to stale caches. 
  •  Lucene - This needs to be centralized. This can be done: a) via JDBC (can work, but there may be issues with speed and table locks), b) swapped out for something like SOLR (runs as a webapp in Tomcat), or c) starting with Liferay 5.2 SP1 there is a clusterlink feature that can be turned on where each node maintains its own replicated cache. If you do not do this, you will see inconsistencies with search and other indexed data that is returned from the DB. 
  • Document Library & Image Gallery - This needs to be centralized. This is because each node keeps the assets locally on the filesystem by default. While the meta-data is in the DB, the files serve up faster this way (vs. BLOBS in a DB). So, you need to either a) point the content repository to be stored in the DB (can work but performance may suffer) via JCRHook in portal properties, or b) mount a path a shared storage (i.e. SAN or other file system storage) and configure each node to connect to this common place via AdvancedFileSystemHook in portal properties. If you do not do this, the meta-data regarding your documents will be in the DB, but when you try to retrieve them, the node may or may not find the document there, physically.

July 13, 2012

[Maven Obfuscation]Using yguard




<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<dependencies>
<dependency>
<groupId>yguard</groupId>
<artifactId>yguard</artifactId>
<version>2.1.0</version>
<scope>system</scope>
<systemPath>${basedir}/../lib/yguard.jar</systemPath>
</dependency>
</dependencies>
<executions>
<execution>
<phase>install</phase>
<configuration>
<tasks>
<property refid="maven.compile.classpath" name="mvn.classpath"></property>
<!-- <echo message="Using Maven Classpath: ${mvn.classpath}" /> -->
<taskdef name="yguard" classname="com.yworks.yguard.YGuardTask" />
<yguard>
<!-- Input file and output file is the same. -->
<inoutpair
in="${project.auto.deploy.dir}/jar/${project.build.finalName}.${project.packaging}"
out="${project.auto.deploy.dir}/jar/${project.build.finalName}_obfuscation.jar" />

<shrink logfile="${project.auto.deploy.dir}/yguard.log.xml">
<property name="error-checking" value="pedantic"/>
<keep>
<class classes="public" methods="public">
<patternset>
<include name="*" />
</patternset>
</class>
</keep>
</shrink>
<!-- Obfuscate classes plus string references. -->
<rename  mainclass="com.pkg.edi.MainParser" logfile="${project.auto.deploy.dir}/yguard.log.xml"
replaceClassNameStrings="true">
<property name="error-checking" value="pedantic"/>
<!-- Keep the only class to be used for easy running and its public 
method main(). 
-->

<adjust replaceContent="true">
       <!-- plain-text class names in the config files will -->
       <!-- be replaced with the obfuscated name versions -->
       <include name="**/*.xml"/>
       <include name="**/*.properties"/>
      </adjust>
       <!-- <adjust replacePath="false">
       keep the complete path to the resources, (gifs...) even if
       package com.mycompany.myapp gets obfuscated by name
       <include name="com/pkg/persistence/*"/>
       </adjust> -->
       <adjust replaceName="true">
       <!-- Replace the .properties files' names with the obfuscated -->
       <!-- versions if the corresponding .class files get obfuscated -->
       <include name="**/*.properties"/>
       </adjust>

<keep>
 
<class classes="public" methods="public">
<patternset>
<include  name="com.pkg.edi.MainParser" />
</patternset>
</class>
</keep>
</rename>

<!-- There are some external libraries used - Maven knows details. -->
<externalclasses>
<pathelement path="${mvn.classpath}" />
</externalclasses>
</yguard>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

July 12, 2012

[Hibernate 4.1]New Feature-Dynamic models


Persistent entities do not necessarily have to be represented as POJO classes or as JavaBean objects at runtime. 
Hibernate also supports dynamic models (using Maps of Maps at runtime) and the representation of entities as DOM4J trees. With this approach, you do not write persistent classes, only mapping files.


By default, Hibernate works in normal POJO mode. You can set a default entity representation mode for a particular SessionFactory using the default_entity_mode configuration option.


The following examples demonstrate the representation using Maps. First, in the mapping file an entity-name has to be declared instead of, or in addition to, a class name:

<hibernate-mapping>


    <class entity-name="Customer">


        <id name="id"
            type="long"
            column="ID">
            <generator class="sequence"/>
        </id>


        <property name="name"
            column="NAME"
            type="string"/>


        <property name="address"
            column="ADDRESS"
            type="string"/>


        <many-to-one name="organization"
            column="ORGANIZATION_ID"
            class="Organization"/>


        <bag name="orders"
            inverse="true"
            lazy="false"
            cascade="all">
            <key column="CUSTOMER_ID"/>
            <one-to-many class="Order"/>
        </bag>


    </class>
    
</hibernate-mapping>





Even though associations are declared using target class names, the target type of associations can also be a dynamic entity instead of a POJO.
After setting the default entity mode to dynamic-map for the SessionFactory, you can, at runtime, work with Maps of Maps:



Session s = openSession();
Transaction tx = s.beginTransaction();


// Create a customer
Map david = new HashMap();
david.put("name", "David");


// Create an organization
Map foobar = new HashMap();
foobar.put("name", "Foobar Inc.");


// Link both
david.put("organization", foobar);


// Save both
s.save("Customer", david);
s.save("Organization", foobar);


tx.commit();
s.close();



One of the main advantages of dynamic mapping is quick turnaround time for prototyping, without the need for entity class implementation. However, you lose compile-time type checking and will likely deal with many exceptions at runtime. 


As a result of the Hibernate mapping, the database schema can easily be normalized and sound, allowing to add a proper domain model implementation on top later on.
Entity representation modes can also be set on a per Session basis:





Session dynamicSession = pojoSession.getSession(EntityMode.MAP);


// Create a customer
Map david = new HashMap();
david.put("name", "David");
dynamicSession.save("Customer", david);
...
dynamicSession.flush();
dynamicSession.close();
...
// Continue on pojoSession




Please note that the call to getSession() using an EntityMode is on the Session API, not the SessionFactory. That way, the new Session shares the underlying JDBC connection, transaction, and other context information. 
This means you do not have to call flush() and close() on the secondary Session, and also leave the transaction and connection handling to the primary unit of work.





[MySQL] How know database schema size using query?


SELECT table_schema "Data Base Name", sum( data_length + index_length ) / 1024 / 1024 "Data Base Size in MB" FROM information_schema.TABLES GROUP BY table_schema;

July 11, 2012

[Liferay] - Dynamic Query with projections with expando


public int getActiveFileEntryCount(long scopeGroupId, long folderId, long companyId,int status) throws Exception{
int activeFoldersCount =  DLFolderServiceUtil.getFileEntriesAndFileShortcutsCount(scopeGroupId, folderId, -1);
if(activeFoldersCount>0){
long classNameId = ClassNameLocalServiceUtil.getClassNameId(DLFileEntry.class.getName());
DynamicQuery folderFileEntriesQuery = DynamicQueryFactoryUtil.forClass( DLFileEntryImpl.class, "fileEntries",PortalClassLoaderUtil.getClassLoader());
folderFileEntriesQuery.setProjection(ProjectionFactoryUtil.property("fileEntries.fileEntryId"));
folderFileEntriesQuery.add(RestrictionsFactoryUtil.eq("fileEntries.folderId", folderId));
folderFileEntriesQuery.add(PropertyFactoryUtil.forName("fileEntries.companyId").eqProperty("fileVersion.companyId"));
folderFileEntriesQuery.add(PropertyFactoryUtil.forName("fileEntries.groupId").eqProperty("fileVersion.groupId"));
DynamicQuery fileEntryVersionQuery = DynamicQueryFactoryUtil.forClass( DLFileVersionModelImpl.class, "fileVersion",PortalClassLoaderUtil.getClassLoader());
fileEntryVersionQuery.setProjection(ProjectionFactoryUtil.property("fileVersion.fileVersionId"));
fileEntryVersionQuery.add(RestrictionsFactoryUtil.eq("fileVersion.companyId", companyId));
fileEntryVersionQuery.add(RestrictionsFactoryUtil.eq("fileVersion.groupId", scopeGroupId));
fileEntryVersionQuery.add(PropertyFactoryUtil.forName("fileVersion.fileEntryId").in(folderFileEntriesQuery));

List<Long> expfiles = DLFileVersionLocalServiceUtil.dynamicQuery(fileEntryVersionQuery,0,Integer.MAX_VALUE);
System.out.println(" -----------classNameId---------- "+classNameId);
System.out.println(" -----------companyId---------- "+companyId);
System.out.println(" -----------folderId---------- "+folderId);
System.out.println(" -----------Total Documents---------- "+expfiles.size()+ "-- Data --"+ expfiles);
if(expfiles.size()>0){

DynamicQuery expiredfolderQuery = DynamicQueryFactoryUtil.forClass( ExpandoValueModelImpl.class, "expandovalue",PortalClassLoaderUtil.getClassLoader());
expiredfolderQuery.add(RestrictionsFactoryUtil.eq("expandovalue.companyId", companyId));
expiredfolderQuery.add(RestrictionsFactoryUtil.eq("expandovalue.classNameId", classNameId));
expiredfolderQuery.add(RestrictionsFactoryUtil.in("classPK", expfiles.toArray()));
expiredfolderQuery.add(RestrictionsFactoryUtil.eq("data","true"));

int expiredDocumentCount = (int)ExpandoValueLocalServiceUtil.dynamicQueryCount(expiredfolderQuery);
System.out.println(" -----------expiredFileEntries Count---------- "+expiredDocumentCount);
activeFoldersCount=activeFoldersCount-expiredDocumentCount;
}
}
return activeFoldersCount;
}