viernes, 5 de septiembre de 2014

Terracotta Projects with maven


I wanted this to be a SOA blog, but in my free time i do some other stuff.

I had been working for some time with the terracotta server. My idea was to share JAVA objects between several virtual machines.

The thing i want to share was simply some maven instructions to start, stop and create the boot-jar (i have lots of problem trying to use their maven plugin)

I just copy all the pom.xml. The only remark about this pom, is that i needed to run the terracotta server in linux and Windows, so i had to create a profile to distinguish between the two enviroments. (There are some OS specific properties)

** The inputs, are the terracotta home, and the config file for the project. I configure a node inside the config file called "MasterNode".

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>testproject.groupId</groupId>
    <artifactId>TestProject</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>TestProject</name>
  
    <profiles>
        <profile>
            <id>Windows</id>
            <activation>
                <os>
                    <family>Windows</family>
                </os>
            </activation>
            <properties>
                <scritp.ext>bat</scritp.ext>
                <tc.home>D:\terracotta-3.7.7</tc.home>
                <tc.conf.file>${basedir}\src\main\resources\Terracotta\tc-config_win.xml</tc.conf.file>
            </properties>
        </profile>
        <profile>
            <id>unix</id>
            <activation>
                <os>
                    <family>unix</family>
                </os>
            </activation>
            <properties>
                <scritp.ext>sh</scritp.ext>
                <tc.home>/Users/user/terracotta-3.7.7</tc.home>
                <tc.conf.file>${basedir}/src/main/resources/Terracotta/tc-config_unix.xml</tc.conf.file>
            </properties>
        </profile>
        <profile>
            <id>tc-start</id>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>exec-maven-plugin</artifactId>
                        <groupId>org.codehaus.mojo</groupId>
                        <version>1.3.2</version>
                        <executions>
                            <execution>
                                <id>tc-start</id>
                                <phase>test</phase>
                                <goals>
                                    <goal>exec</goal>
                                </goals>
                                <configuration>
                                    <executable>${tc.home}${file.separator}bin${file.separator}start-tc-server.${scritp.ext}</executable>
                                    <arguments>
                                        <argument>-n</argument>
                                        <argument>MasterNode</argument>
                                        <argument>-f</argument>
                                        <argument>${tc.conf.file}</argument>
                                    </arguments>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>              
                </plugins>
            </build>
        </profile>
        <profile>
            <id>tc-stop</id>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>exec-maven-plugin</artifactId>
                        <groupId>org.codehaus.mojo</groupId>
                        <version>1.3.2</version>
                        <executions>
                            <execution>
                                <id>tc-stop</id>
                                <phase>test</phase>
                                <goals>
                                    <goal>exec</goal>
                                </goals>
                                <configuration>
                                    <executable>${tc.home}${file.separator}bin${file.separator}stop-tc-server.${scritp.ext}</executable>
                                    <arguments>
                                        <argument>-n</argument>
                                        <argument>MasterNode</argument>
                                        <argument>-f</argument>
                                        <argument>${tc.conf.file}</argument>
                                    </arguments>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>              
                </plugins>
            </build>
        </profile>
        <profile>
            <id>tc-boot-jar</id>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>exec-maven-plugin</artifactId>
                        <groupId>org.codehaus.mojo</groupId>
                        <version>1.3.2</version>
                        <executions>
                            <execution>
                                <id>tc-boot-jar</id>
                                <phase>test</phase>
                                <goals>
                                    <goal>exec</goal>
                                </goals>
                                <configuration>
                                    <executable>${tc.home}${file.separator}platform${file.separator}bin${file.separator}make-boot-jar.${scritp.ext}</executable>
                                    <arguments>
                                        <argument>-f</argument>
                                        <argument>${tc.conf.file}</argument>
                                    </arguments>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>              
                </plugins>
            </build>
        </profile>        
    </profiles>
</project>

sábado, 5 de julio de 2014

OSB Custom Proxy Logging

In several projects what i normally did, was to build a Proxy service of logging. Each time i want a log a message i simply call this service(Some times in a database or in a file).

I have seen some blogs on how to redirect the OSB logging and i wanted to try this approach to see how far i was able to get. The idea, is to filter the server log once the "Executing tracing" and the "Message Tracing" was checked, and use them like the traces of the services.

I spent some time finding the way to customize the native logging of the Oracle Service BUS (OSB), what i want  was the following.
  • Capture and filter all the message and executing tracing of a Proxy Service.
  • Separate the log files by Proxy Service 
  • Don't let the server log (startup and diagnostics) mixes with the business log (Execution of services) 
Update 01/05/2015: I wrote another blog about this same issue but using the JDK Logging instead of log4j as default logging implementation. You can see all the details in Filter Weblogic Logs

This are the steps to follow.

The general idea is to create a startup class that modifies the file appender of the weblogic server, adding a custom filter. The filter is able to control the traces and redirect the information.
  1. Activate the Log4j tracing of the Weblogic server. Use the instructions of the following link
  1. Create a startup class and add the filter to the appender. It's important to note that the log4j filters works in the order they are configured, so we have to put our filter the first.
  2. package com.carlgira.osb.trace;
    
    import org.apache.log4j.AppenderSkeleton;
    import org.apache.log4j.Logger;
    
    import weblogic.logging.log4j.AppenderNames;
    import weblogic.logging.log4j.Log4jLoggingHelper;
    
    import com.carlgira.osb.trace.OSBTraceFilter;
    
    public class OSBLoggerConf 
    {
     public static void main(String[] args) 
     {
    
      try 
      {
       // First parameter args[0] --> Regex Filter
       // Second parametro args[1] --> Default loggerName
       
       String regexFilter =  args[0];
       String defaultLogger  = args[1];
       
       Logger serverLogger = Log4jLoggingHelper.getLog4jServerLogger();
    
       // Create custom Filter
       OSBTraceFilter osbFilter = new OSBTraceFilter(regexFilter);
       osbFilter.setDefaultLogger(defaultLogger);
    
       // Getting file appender
       AppenderSkeleton app = (AppenderSkeleton) serverLogger.getAppender(AppenderNames.LOG_FILE_APPENDER);
       
       // Add our custom filter as the first Filter and put the others existing filter after
       osbFilter.setNext(app.getFirstFilter());
       app.clearFilters();
       app.addFilter(osbFilter);
      }
      catch (Exception e) 
      {
       e.printStackTrace();
      }
     }
    }
    
    
    
  3. Create a filter class. Using the string "[OSB Tracing]". The filter don't allow to write the messages on the log server. 
  4. The next thing is to use other log4j or logback (i use logback) logger to redirect the messages. We get a logger name using the name of the Proxy. To capture the name of the Proxy i use a regular expression.
  5. The problem was that the Proxy name it's just in a few traces, with the inbound and outbound messages. So all the other traces in the middle of the Proxy does not have the Proxy name. The solution i found for this, was to use de MDC of the logging implementation (The MDC is like a buffer that can be used for saving some context information, that information it's just available in the live of the current thread of the service. A Proxy service creates 2 threads one for the request pipeline and other for the response pipeline)
  6. Save the Proxy name using the "contextId". (unique identifier)
  7. Finally just write the log using a new logger.
  8. package com.carlgira.osb.trace;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import org.apache.log4j.spi.Filter;
    import org.apache.log4j.spi.LoggingEvent;
    import org.slf4j.LoggerFactory;
    import org.slf4j.MDC;
    
    import weblogic.logging.WLLevel;
    import weblogic.logging.log4j.WLLog4jLogEvent;
    import ch.qos.logback.classic.Logger;
    
    public class OSBTraceFilter extends Filter {
    
     private String filter;
     private String defaultLogger;
    
     private Pattern patternFilter, patternServiceRef ;
    
     public OSBTraceFilter(String filter)
     {
      patternFilter = Pattern.compile(filter);
      patternServiceRef = Pattern.compile("Service\\sRef");
      this.filter = filter;
     }
    
     
     public int decide(LoggingEvent arg0) 
     {
      int level = WLLevel.TRACE_INT;
      String message = arg0.getMessage().toString();
      Matcher matcherFilter = patternFilter.matcher(message);
      
      // Regex filter
      if (matcherFilter.find())
      {
       String loggerName = defaultLogger;
       WLLog4jLogEvent event = (WLLog4jLogEvent) arg0;
       String cid = event.getDiagnosticContextId();
       String label = parseLabel(message);
    
       Matcher matcherServiceRef = patternServiceRef.matcher(message);
       boolean serviceRefPattern = matcherServiceRef.find(); 
       
       // Check if the proxyName is on the trace
       if (serviceRefPattern)  
       {
        level = WLLevel.DEBUG_INT;
        try 
        {
         // Save the Proxy as the LoggerName
         if (MDC.get(cid) == null)
         {
          loggerName = parseProxyName(message).trim().replaceAll("/",".");
          MDC.put(cid, loggerName);
         }
        }
        catch (Exception e) 
        {
         loggerName = defaultLogger;
        }
       }
       // Retrieve the loggerName
       if (MDC.get(cid) != null) 
       {
        loggerName = MDC.get(cid);
       }
    
       try
       {
        // Write the information with logback
        Logger logger = (Logger)LoggerFactory.getLogger(defaultLogger);
    
        if(level == WLLevel.DEBUG_INT)
        {
         logger.debug("{}, message = {}" , label ,message);
        }
        else if(level == WLLevel.TRACE_INT)
        {
         logger.trace("{}, message = {}" , label ,message);
        }
        else
        {
         logger.error("{}, message = {}" , label ,message);
        }
       }
       catch(Exception e)
       {
        e.printStackTrace();
       }
       return DENY;
      } 
      else 
      {
       return NEUTRAL;
      }
    
     }
    
     public String getFilter() {
      return filter;
     }
    
     public void setFilter(String filter) {
      this.filter = filter;
     }
     
    
     public String getDefaultLogger() {
      return defaultLogger;
     }
    
     public void setDefaultLogger(String defaultAppender) {
      this.defaultLogger = defaultAppender;
     }
     /**
      * Parse the information after de OSB Tracing string.
      * @param message
      * @return
      */
     public String parseLabel(String message)
     {
      String response = "";
      try
      {
       Pattern pattern = Pattern.compile("(\\[OSB Tracing\\] )(.*)");
       Matcher matcher = pattern.matcher(message);
       
       response = matcher.group(2);
       if (response != null && response.trim().length() > 0) 
       {
        return response;
       }
      }
      catch(Exception e)
      {
       return response;
      } 
    
      return response;
     }
    
     /**
      * Parse de Proxy Name of the log message
      * @param message
      * @return
      * @throws Exception
      */
     public String parseProxyName(String message) throws Exception 
     {
      String response = "";
      Pattern pattern = Pattern.compile("(Service Ref = )(.*)");
      Matcher matcher = pattern.matcher(message);
      response = matcher.group(2);
      if (response != null && response.trim().length() > 0) 
      {
       return response;
      }
      
      throw new Exception();
     }
    }
    
    
  9. Put the jars over the lib path of the domain user_projects/domains/base_domain/lib/, wlog4j.jar, logback-core-1.0.13.jar, logback-classic-1.0.13, sfl4j-api-1.7.5.jar and include the jar with the filter code.
  10. Create the startup class resource in Weblogic. Following these instructions http://docs.oracle.com/cd/E21764_01/apirefs.1111/e13952/taskhelp/startup_shutdown/ConfigureStartupAndShutdownClasses.html. Put as parameters the next values: \[OSB\sTracing\] OSBDefaultLogger
  11. Configure the server with the logback file using the property -Dlogback.configurationFile=/home/carlgira/Oracle/logback.xml
  12. 
      
      
        /home/carlgira/Oracle/logs/default.log
        
          %d{yyyyMMdd HH:mm:ss.SSS} %5p %x %10c %m%n
        
        
          0
          99
          /home/carlgira/Oracle/Middleware/default.log%i
        
        
          5MB
        
      
       
        /home/carlgira/Oracle/logs/template_ps.log
        
          %d{yyyyMMdd HH:mm:ss.SSS} %5p %x %10c %m%n
        
        
          0
          99
          /home/carlgira/Oracle/logs/template_ps.log%i
        
        
          5MB
        
      
    
     
        
       
    
       
        
       
    
    
  13. Reboot the OSB server.

As i comment before i prefer to use logback instead of log4j. It has the same functionality of log4j corrects some behavior and what a love the most, it's to be able to configure in the xml file, the scan period to re-load the configuration

OBSERVATIONS


  •  I'am pretty sure that a better approach to make this same implementation is to use a MBEAN instead of a  startup class, so the filter (or filters) could be added or removed on runtime.
  • The filters of this post are specially for OSB, but the same approach could be followed to filter anything of the Weblogic logs. (The traces of the BPM or BPEL processes for example)

REFERENCES

Here a some links that i use as base:

Redirect log records to any other destination
http://tdanas.blogspot.com.es/2013/05/how-to-create-weblogic-startup-class.html

OSB custom Jdbc Appender
http://frommyworkshop.blogspot.com.es/2010/10/oracle-service-bus-logging-with-custom.html

OSB Executing and Message Tracing
http://jvzoggel.wordpress.com/2012/01/23/osb_tracing_runtime/

Configuring Weblogic Logging Services
http://docs.oracle.com/cd/E23943_01/web.1111/e13739/filtering.htm

jueves, 3 de julio de 2014

Soa Suite 11g MDS deploy with Maven

I had see lots of post where to deploy the MDS with ant. My intention is to give the configuration i follow to make a MDS maven project.

I follow the post of Edwin Biemond http://biemond.blogspot.com.es/2009/11/soa-suite-11g-mds-deploy-and-removal.html  and adapt the files to use them with maven.


The configuration needed in the pom:

        
<properties>
  <!-- Server-->
  <wl.server.url>http://localhost:33000</wl.server.url>
  <wl.user>weblogic</wl.user>
  <wl.pass>welcome1</wl.pass>
  <wl.home.mdw>C:\Oracle\MDWJdev</wl.home.mdw>
  <wl.home.mdw.jdev>C:\Oracle\MDWJdev\jdeveloper</wl.home.mdw.jdev>
  <wl.home.mdw.jdk>C:\Oracle\MDWJdev\jdeveloper</wl.home.mdw.jdk>
  <wl.home.mdw.wls>C:\Oracle\MDWJdev\wlserver_10.3</wl.home.mdw.wls>
 </properties>

 <profiles>
  <profile>
   <id>deployMDSServer1</id>
   <build>
    <plugins>
     <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-antrun-plugin</artifactId>
      <version>1.7</version>
      <dependencies>
       <dependency>
        <groupId>ant-contrib</groupId>
        <artifactId>ant-contrib</artifactId>
        <version>1.0b3</version>
        <exclusions>
         <exclusion>
          <groupId>ant</groupId>
          <artifactId>ant</artifactId>
         </exclusion>
        </exclusions>
       </dependency>
      </dependencies>
      <executions>
       <execution>
        <id>deployMDSServer1</id>
        <phase>install</phase>
        <goals>
         <goal>run</goal>
        </goals>
        <configuration>
         <tasks>
          <ant antfile="${basedir}\build.xml">
           <property name="wl.serverURL" value="${wl.server.url}" />
           <property name="wl.user" value="${wl.user}" />
           <property name="wl.password" value="${wl.pass}" />
           <property name="mds.reposistory"
            value="${basedir}/src/main/resources/mds/apps" />
           <property name="tmp.output.dir" value="${basedir}" />
           <property name="wn.bea.home" value="${wl.home.mdw}" />
           <property name="oracle.home" value="${wl.home.mdw.jdev}" />
           <property name="java.passed.home" value="${wl.home.mdw.jdk}" />
           <property name="wl_home" value="${wl.home.mdw.wls}" />
           <target name="deployMDS" />
          </ant>
         </tasks>
        </configuration>
       </execution>
      </executions>
     </plugin>
    </plugins>
   </build>
  </profile>



The reduced version of the properties file:
mds.applications=apps
mds.undeploy=false

# dev deployment server weblogic
wl.overwrite=true
wl.forceDefault=true

Finally the build.xml:
<?xml version="1.0" encoding="iso-8859-1"?>
<project name="soaDeployAll" default="deployMDS">
    <echo>basedir ${basedir}</echo>

    <property file="${basedir}\build.properties"/>  
    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>


    <target name="unDeployMDS">
        <echo>undeploy MDS</echo>
        <foreach list="${mds.applications}" param="mds.application" target="undeployMDSApplication" inheritall="true" inheritrefs="false"/>
    </target>

    <target name="deployMDS">
        <echo>undeploy and deploy MDS</echo>
        <if> 
          <equals arg1="${mds.undeploy}" arg2="true"/>
          <then>
            <foreach list="${mds.applications}" param="mds.application" target="undeployMDSApplication" inheritall="true" inheritrefs="false"/>
          </then>
        </if>
        <foreach list="${mds.applications}" param="mds.application" target="deployMDSApplication" inheritall="true" inheritrefs="false"/>
    </target>

    <target name="deployMDSApplication">
        <echo>deploy MDS application ${mds.application}</echo>

        <echo>remove and create local MDS temp</echo>
        <property name="mds.deploy.dir" value="${tmp.output.dir}/${mds.application}"/>

        <delete dir="${mds.deploy.dir}"/>
        <mkdir dir="${mds.deploy.dir}"/>

        <echo>create zip from file MDS store</echo>
      <zip destfile="${mds.deploy.dir}/${mds.application}_mds.jar" compress="false"> 
        <fileset dir="${mds.reposistory}" includes="/**"/>
      </zip>

        <echo>create zip with MDS jar</echo>
      <zip destfile="${mds.deploy.dir}/${mds.application}_mds.zip" compress="false"> 
        <fileset dir="${mds.deploy.dir}" includes="*.jar"/>
      </zip>

        <propertycopy name="deploy.serverURL"    from="wl.serverURL"/>
        <propertycopy name="deploy.overwrite"    from="wl.overwrite"/>
        <propertycopy name="deploy.user"         from="wl.user"/>
        <propertycopy name="deploy.password"     from="wl.password"/>
        <propertycopy name="deploy.forceDefault" from="wl.forceDefault"/>

        <echo>deploy MDS app</echo>

        <echo>deploy on ${deploy.serverURL} with user ${deploy.user}</echo>
        <echo>deploy sarFile ${mds.deploy.dir}/${mds.application}_mds.zip</echo>

        <ant antfile="${oracle.home}/bin/ant-sca-deploy.xml" inheritAll="false" target="deploy">
             <property name="wl_home" value="${wl_home}"/>
             <property name="oracle.home" value="${oracle.home}"/>
             <property name="serverURL" value="${deploy.serverURL}"/>
             <property name="user" value="${deploy.user}"/>
             <property name="password" value="${deploy.password}"/>
             <property name="overwrite" value="${deploy.overwrite}"/>
             <property name="forceDefault" value="${deploy.forceDefault}"/>
             <property name="sarLocation" value="${mds.deploy.dir}/${mds.application}_mds.zip"/>
        </ant> 

    </target>

    <target name="undeployMDSApplication">
        <echo>undeploy MDS application ${mds.application}</echo>

        <propertycopy name="deploy.serverURL"    from="wl.serverURL"/>
        <propertycopy name="deploy.overwrite"    from="wl.overwrite"/>
        <propertycopy name="deploy.user"         from="wl.user"/>
        <propertycopy name="deploy.password"     from="wl.password"/>
        <propertycopy name="deploy.forceDefault" from="wl.forceDefault"/>

         <echo>undeploy MDS app folder apps/${mds.application} </echo>
         <ant antfile="${oracle.home}/bin/ant-sca-deploy.xml" inheritAll="false" target="removeSharedData">
              <property name="wl_home" value="${wl_home}"/>
              <property name="oracle.home" value="${oracle.home}"/>
              <property name="serverURL" value="${deploy.serverURL}"/>
              <property name="user" value="${deploy.user}"/>
              <property name="password" value="${deploy.password}"/>
              <property name="folderName" value="${mds.application}"/>
         </ant> 
    </target>

</project>

The structure of the project must be like this

- my-project
  - src/
    - main/
      - java/
        - resources/
          - mds/
            - apps/
              - upload_test.txt
 - build.properties
 - build.xml
 -  pom.xml

        

Thats it.