Monday, December 26, 2011

Functional x Imperative ?

http://rosettacode.org/wiki/Roman_numerals/Decode#Java

[dave@dave lisp]$ clisp 
i
. i i i I i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I I I 8 8 8 8 8 o 8 8
I I \ `+' / I I 8 8 8 8 8 8
I \ `-+-' / I 8 8 8 ooooo 8oooo
\ `-__|__-' / 8 8 8 8 8
`--___|___--' 8 o 8 8 o 8 8
| ooooo 8oooooo ooo8ooo ooooo 8
--------+--------

Welcome to GNU CLISP 2.49 (2010-07-07) <http://clisp.cons.org/>




Code ( taken from Object Oriented Common Lisp )
defun roman-to-decimal  (num-list)
(if ( endp num-list)
0
(+ (or
(and (cdr num-list)
(< (numeral-to-decimal (car num-list))
(numeral-to-decimal (cadr num-list)))
(- (numeral-to-decimal (car num-list))))
(numeral-to-decimal (car num-list)))
(roman-to-decimal (cdr num-list)))))

(load "roman-to-decimal.lisp")

[7]> (roman-to-decimal '(M C M L X I X ))
1969
[8]> (trace roman-to-decimal)
;; Tracing function ROMAN-TO-DECIMAL.
(ROMAN-TO-DECIMAL)
[9]> (roman-to-decimal '(M C M L X I X ))
1. Trace: (ROMAN-TO-DECIMAL '(M C M L X I X))
2. Trace: (ROMAN-TO-DECIMAL '(C M L X I X))
3. Trace: (ROMAN-TO-DECIMAL '(M L X I X))
4. Trace: (ROMAN-TO-DECIMAL '(L X I X))
5. Trace: (ROMAN-TO-DECIMAL '(X I X))
6. Trace: (ROMAN-TO-DECIMAL '(I X))
7. Trace: (ROMAN-TO-DECIMAL '(X))
8. Trace: (ROMAN-TO-DECIMAL 'NIL)
8. Trace: ROMAN-TO-DECIMAL ==> 0
7. Trace: ROMAN-TO-DECIMAL ==> 10
6. Trace: ROMAN-TO-DECIMAL ==> 9
5. Trace: ROMAN-TO-DECIMAL ==> 19
4. Trace: ROMAN-TO-DECIMAL ==> 69
3. Trace: ROMAN-TO-DECIMAL ==> 1069
2. Trace: ROMAN-TO-DECIMAL ==> 969
1. Trace: ROMAN-TO-DECIMAL ==> 1969
1969



Haskell
http://www.haskell.org/haskellwiki/Roman_numerals#More-than-one_liner
http://www.cs.york.ac.uk/ftpdir/pub/haskell/contrib/Roman.hs
[dave@dave haskell]$ ghci
GHCi, version 6.12.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Prelude> :l Roman.hs
[1 of 1] Compiling Main ( Roman.hs, interpreted )
Ok, modules loaded: Main.
*Main> fromRoman "MCMLXIX"
1969




Simple Java implementation
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RomanToDecimal {

public static Map<String, Integer> romanNumberMap = new HashMap<String, Integer>();
static {
// ( (I 1) (V 5) (X 10) (L 50) (C 100) (D 500) (M 1000)))
romanNumberMap.put("I", 1);
romanNumberMap.put("V", 5);
romanNumberMap.put("X", 10);
romanNumberMap.put("L", 50);
romanNumberMap.put("C", 100);
romanNumberMap.put("D", 500);
romanNumberMap.put("M", 1000);
}

public static void main(String[] args) {

roman2dec("IV");

roman2dec("LXIV");

roman2dec("XCVIII");

roman2dec("MCMLXIX");

}

private static int roman2dec(String roman) {

int out = 0;

List<Integer> list = new ArrayList<Integer>();

for (int i = 0; i < roman.length(); i++) {
list.add(romanNumberMap.get(String.valueOf(roman.charAt(i))));
}

System.out.println("list=" + list);

while (list.size() > 0) {
if ((list.size() > 1) && (list.get(0) < list.get(1))) {
out -= list.remove(0);
} else {
out += list.remove(0);
}
System.out.println(" list=" + list + " out=" + out);
}

System.out.println("roman=" + roman + " dec=" + out);

return out;

}

}



list=[1, 5]
list=[5] out=-1
list=[] out=4
roman=IV dec=4
list=[50, 10, 1, 5]
list=[10, 1, 5] out=50
list=[1, 5] out=60
list=[5] out=59
list=[] out=64
roman=LXIV dec=64
list=[10, 100, 5, 1, 1, 1]
list=[100, 5, 1, 1, 1] out=-10
list=[5, 1, 1, 1] out=90
list=[1, 1, 1] out=95
list=[1, 1] out=96
list=[1] out=97
list=[] out=98
roman=XCVIII dec=98
list=[1000, 100, 1000, 50, 10, 1, 10]
list=[100, 1000, 50, 10, 1, 10] out=1000
list=[1000, 50, 10, 1, 10] out=900
list=[50, 10, 1, 10] out=1900
list=[10, 1, 10] out=1950
list=[1, 10] out=1960
list=[10] out=1959
list=[] out=1969
roman=MCMLXIX dec=1969

Sunday, November 6, 2011

Java EE6 - POJO injection

Simplest Possible POJO Injection Example With Java EE 6
http://www.adam-bien.com/roller/abien/entry/simplest_possible_pojo_injection_example

Annotation Type Inject

http://download.oracle.com/javaee/6/api/javax/inject/Inject.html


Contexts and Dependency Injection for the Java EE Platform

http://www.oracle.com/technetwork/articles/javaee/javaee6overview-141808.html#webbeans



TestInject class
package testinject;

import javax.ejb.EJB;
import javax.inject.Named;

import testejb.BackendBeanLocal;
import testservice.MasterDataCacheLocal;

@Named("TestInject")
public class TestInject {


public TestInject(){
System.out.println("TestInject : constructor");
}

@EJB
MasterDataCacheLocal masterDataCache;

@EJB
BackendBeanLocal service;

public void callService(){

if(masterDataCache.get("dave") == null){
masterDataCache.store("dave","dave");
}

System.out.println("TestInject: callService" );
service.runService();

}

}



Inject POJO in Test Servlet
  @Inject
TestInject testInject;

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

out.println("testInject.callService()<br>");
testInject.callService();






This file is necessary to force to injection
/testWEB/WebContent/WEB-INF/beans.xml
http://download.oracle.com/javaee/6/tutorial/doc/gjbnz.html

</beans>




TestServlet

package testWEB;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.ejb.EJB;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import testinject.TestInject;
import testservice.TestServiceLocal;

/**
* Servlet implementation class TestServlet
*/
@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#HttpServlet()
*/
public TestServlet() {
super();
// TODO Auto-generated constructor stub
}

@EJB TestServiceLocal service;

@Inject
TestInject testInject;

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
PrintWriter out = res.getWriter();
res.setContentType("text/html");

HttpSession session = req.getSession(true);

String heading;
Integer accessCount = new Integer(0);
if (session.isNew()) {
heading = "Welcome, Newcomer";
} else {
heading = "Welcome Back";
Integer oldAccessCount = (Integer) session
.getAttribute("accessCount");
if (oldAccessCount != null) {
accessCount = new Integer(oldAccessCount.intValue() + 1);
}
}
session.setAttribute("accessCount", accessCount);

out.println("service.callService()<br>");
service.callService();

out.println("testInject.callService()<br>");
testInject.callService();

out.println("<H1>This is a password protected resource</H1>");
out.println("<PRE>");
out.println("User Name: " + req.getRemoteUser());
String name = (req.getUserPrincipal() == null) ? null : req
.getUserPrincipal().getName();
out.println("Principal Name: " + name);
out.println("Authentication Type: " + req.getAuthType());
out.println("Is a Manager: " + req.isUserInRole("AppRole"));
out.println("</PRE>");
out.println(
"<H1 ALIGN=\"CENTER\">" + heading + "</H1>\n" +
"<H2>Update Servlet!!! Information on Your Session:</H2>\n" +
"<TABLE BORDER=1 ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD70\">\n" +
" <TH>Info Type<TH>Value\n" +
"<TR>\n" +
" <TD>ID\n" +
" <TD>" + session.getId() + "\n" +
"<TR>\n" +
" <TD>Creation Time is\n" +
" <TD>" + new Date(session.getCreationTime()) + "\n" +
"<TR>\n" +
" <TD>Time of Last Access\n" +
" <TD>" + new Date(session.getLastAccessedTime()) + "\n" +
"<TR>\n" +
" <TD>Number of Previous Accesses\n" +
" <TD>" + accessCount + "\n" +
"</TABLE>\n");
out.println("</BODY></HTML>");


}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}

}







Application Server log

[#|2011-11-06T22:49:45.979+0100|INFO|glassfish3.1.1|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=17;_ThreadName=Thread-2;|WEB0671: Loading application [testEAR#testWEB.war] at [testWEB]|#]

[#|2011-11-06T22:49:46.002+0100|INFO|glassfish3.1.1|javax.enterprise.system.tools.admin.org.glassfish.deployment.admin|_ThreadID=17;_ThreadName=Thread-2;|testEAR was successfully deployed in 911 milliseconds.|#]

[#|2011-11-06T22:50:30.394+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|TestInject : constructor|#]

[#|2011-11-06T22:50:30.401+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|principal=dave|#]

[#|2011-11-06T22:50:30.404+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|MasterDataCache.initCache|#]

[#|2011-11-06T22:50:30.409+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|MasterDataCache.get dave|#]

[#|2011-11-06T22:50:30.411+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|TestService: masterDataCache.store|#]

[#|2011-11-06T22:50:30.413+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|MasterDataCache.store dave|#]

[#|2011-11-06T22:50:30.413+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|TestService: callService|#]

[#|2011-11-06T22:50:30.415+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|BackendBean: runService|#]

[#|2011-11-06T22:50:30.417+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|MasterDataCache.get dave|#]

[#|2011-11-06T22:50:30.417+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|TestInject: callService|#]

[#|2011-11-06T22:50:30.418+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|BackendBean: runService|#]

EJB 3.1 Singleton example

Simplest Possible EJB 3.1 Singleton - Injected Into Servlet 3.0, WAR Deployment
http://www.adam-bien.com/roller/abien/entry/simplest_possible_ejb_3_14

Java EE6 Tutorial : A Singleton Session Bean Example: counter
http://download.oracle.com/javaee/6/tutorial/doc/gipvi.html

A singleton session bean is instantiated once per application and exists for the lifecycle of the application. Singleton session beans are designed for circumstances in which a single enterprise bean instance is shared across and concurrently accessed by clients.

Singleton bean - implements cache

package testservice;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;


/**
* Session Bean implementation class MasterDataCache
*/
@javax.ejb.Singleton
public class MasterDataCache implements MasterDataCacheLocal {

private Map cache;

@PostConstruct
public void initCache() {
System.out.println("MasterDataCache.initCache");
this.cache = new HashMap();
}

public Object get(String key) {
System.out.println("MasterDataCache.get " + key);
return this.cache.get(key);
}

public void store(String key, Object value) {
System.out.println("MasterDataCache.store " + key);
this.cache.put(key, value);
}

}




TestService Session Bean
package testservice;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.EJBContext;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;

import testejb.BackendBeanLocal;

/**
* Session Bean implementation class TestService
*/
@Stateless
public class TestService implements TestServiceRemote, TestServiceLocal {

@EJB
MasterDataCacheLocal masterDataCache;

@EJB
BackendBeanLocal service;

@Resource SessionContext sessionContext;

public void callService(){

System.out.println("principal=" + sessionContext.getCallerPrincipal());

if(masterDataCache.get("dave") == null){
System.out.println("TestService: masterDataCache.store" );
masterDataCache.store("dave","dave");
} else {
System.out.println("TestService: masterDataCache get" );
}

System.out.println("TestService: callService" );
service.runService();

}

}

Security in Glassfish 3.1 ( Java EE 6)

Introduction to Security in the Java EE Platform
http://download.oracle.com/docs/cd/E19798-01/821-1841/6nmq2cpig/index.html
Getting Started Securing Web Applications
http://download.oracle.com/docs/cd/E19798-01/821-1841/bncas/index.html

In EJB caller principal can be obtained from injected SessionContext using
@Resource SessionContext sessionContext;


    System.out.println("principal=" + sessionContext.getCallerPrincipal());




web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>testWEB</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>TestServlet</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>AppRole</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>default</realm-name>
</login-config>
<security-role>
<role-name>AppRole</role-name>
</security-role>
</web-app>


sun-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
<sun-web-app error-url="">
<context-root>/testWEB</context-root>
<security-role-mapping>
<role-name>AppRole</role-name>
<principal-name>dave</principal-name>
</security-role-mapping>

<security-role-mapping>
<role-name>AppRole</role-name>
<group-name>AppGroup</group-name>
</security-role-mapping>
<class-loader delegate="true"/>
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class java code.</description>
</property>
</jsp-config>

</sun-web-app>


Add user dave in group AppGroup using server console.
Group AppGroup must be mapped to security role AppRole defined in descriptors.


Sunday, October 9, 2011

Weblogic Custom Role Mapping Provider

Developing Security Providers for Oracle WebLogic Server 11g Release 1 (10.3.3)
Role Mapping Providers
http://download.oracle.com/docs/cd/E14571_01/web.1111/e13718/rm.htm

The sample security providers (available at https://codesamples.samplecode.oracle.com/servlets/tracking?id=S224 on the Oracle Technology Network Web site)

Build process for Identity Asserter
http://weblogic-wonders.com/weblogic/2010/03/15/custom-identity-asserter-for-weblogic-server/


Build process for Role Mapping Provider
- download Weblogic Sample Security Providers
- unzip SampleSecurityProviders91
- set WLS environment
. /app/wlserver_10.3/server/bin/setWLSEnv.sh 

- create ant build script build.xml
- copy commo.dtd to build dir
 find /app/wlserver_10.3/ commo.dtd 
cp /app/wlserver_10.3/server/lib/commo.dtd .

- run ant
- copy created jar to $WL_HOME/server/lib/mbeantypes
cp SimpleSampleRoleMapper.jar /usr/app/wlserver_10.3/server/lib/mbeantypes/

- restart server
- create new Role Mapper using WLS console


Configure new Role Mapper



Files in build dir

build.xml  
SimpleSampleRoleMapper.jar
SimpleSampleRoleMapper.xml
commo.dtd
SimpleSampleRoleMapperDatabase.java
SimpleSampleSecurityRoleImpl.java


build.xml
<project name="Expenselink Build" default="all" basedir=".">
<property name="fileDir" value="test" />

<target name="all" depends="build"/>

<target name="build" depends="clean,build.mdf,build.mjf"/>

<target name="clean">
<delete dir="${fileDir}" failonerror="false"/>
<delete file="SimpleSampleRoleMapper.jar" failonerror="false"/>
<echo message="Clean finish" />
</target>

<!-- helper to build an MDF (mbean definition file) -->
<target name="build.mdf">
<java dir="${basedir}" fork="false" classname="weblogic.management.commo.WebLogicMBeanMaker">
<arg line="-files ${fileDir}" />
<arg value="-createStubs" />
<arg line="-MDF SimpleSampleRoleMapper.xml" />
</java>
<echo message="Created Supporting Classes" />
</target>

<target name="build.mjf">

<copy todir="${fileDir}" flatten="true">
<fileset dir=".">
<include name="*.java" />
</fileset>
</copy>

<java dir="${basedir}" fork="false" classname="weblogic.management.commo.WebLogicMBeanMaker">
<arg line="-MJF SimpleSampleRoleMapper.jar" />
<arg line="-files ${fileDir}" />
</java>
<echo message="Created Mbean Jar" />
</target>

</project>



AdminServer log - IdentityAsserter and RoleMapper
SimpleSampleIdentityAsserterProviderImpl.assertIdentity
Type = SamplePerimeterAtnToken
Token = [B@9a9036
userName = dave
SimpleSampleRoleMapperProviderImpl.getRoles
subject = Subject:
Principal: dave
Principal: DaveGroup
Private Credential: dave

resource = type=<url>, application=_auto_generated_ear_, contextPath=/daveWeb, uri=/AuthenticationSnoop, httpMethod=GET
roles = {Anonymous=Anonymous, DaveRole=DaveRole}
SimpleSampleRoleMapperProviderImpl.getRoles
subject = Subject:
Principal: dave
Principal: DaveGroup
Private Credential: dave

resource = type=<url>, application=_auto_generated_ear_, contextPath=/daveWeb, uri=/
roles = {Anonymous=Anonymous, DaveRole=DaveRole}



DaveRole in Weblogic LDAP - using JXplorer LDAP browser

Weblogic Embedded LDAP

Configuration steps for LDAP connection to Weblogic domain
http://weblogic-wonders.com/weblogic/2010/05/20/connecting-to-weblogic-server-embedded-ldap-using-ldap-browser/

Download LDAP browser
http://jxplorer.org/

DaveGroup
DaveGroup
ldap:///ou=people,ou=myrealm,dc=base_domain??sub?(&(objectclass=person)(wlsMemberOf=cn=DaveGroup,ou=groups,ou=myrealm,dc=base_domain))



dave
dave user
cn=DaveGroup,ou=groups,ou=myrealm,dc=base_domain


DaveRole

Saturday, October 8, 2011

Weblogic Custom Identity Asserter

JAAS Authentication Tutorial
http://download.oracle.com/javase/6/docs/technotes/guides/security/jaas/tutorials/GeneralAcnOnly.html

JAAS Authorization Tutorial
http://download.oracle.com/javase/6/docs/technotes/guides/security/jaas/tutorials/GeneralAcnAndAzn.html

JavaTM Authentication and Authorization Service (JAAS)
LoginModule Developer's Guide
http://download.oracle.com/javase/6/docs/technotes/guides/security/jaas/JAASLMDevGuide.html




This describes how to add Identity Asserter into Weblogic.
This is needed when identity of user is authenticated at external component. User id is provided as token in HTTP header of request.

Code is taken from Weblogic samples
code-sample ID S224: Sample Security Providers for WLS 9.1
https://codesamples.samplecode.oracle.com/servlets/tracking?id=S224

The same code is described in WLS documentation here
Developing Security Providers for Oracle WebLogic Server 11g Release 1 (10.3.3)
Identity Assertion Providers
http://download.oracle.com/docs/cd/E14571_01/web.1111/e13718/ia.htm#i1176936
http://download.oracle.com/docs/cd/E14571_01/web.1111/e13718/ia.htm#i1176936

O'Reilly Book Excerpts: WebLogic: The Definitive Guide
Java and Security, Part 2
http://onjava.com/pub/a/onjava/excerpt/weblogic_chap17/index1.html?page=1

Build process is decribed here
Custom Identity Asserter for Weblogic Server
http://weblogic-wonders.com/weblogic/2010/03/15/custom-identity-asserter-for-weblogic-server

http://java4pro.typepad.com/enterprise_solution_in_ja/2007/10/jaas-implementa.html

Identity Asserter is created as Weblogic MBean.
<?xml version="1.0" ?>
<!DOCTYPE MBeanType SYSTEM "commo.dtd">

<!-- MBean Definition File (MDF) for the Simple Sample Identity Asserter.

Copyright (c) 2002 by BEA Systems, Inc. All Rights Reserved.
-->

<!-- Declare your mbean.

Since it is for an identity asserter, it must extend the
weblogic.management.security.authentication.IdentityAsserter mbean.

The Name and DisplayName must be the same.
They specify the name that will appear on the
console for this provider.

Set the PeristPolicy to "OnUpdate" so that if an attribute
value is changed, the new value is written to disk immediately.
See the "Developing Security Services" manual for more info.

Note that since this is an xml document, you can't use double
quotes directly. Instead you need to use &quot;

Note that setting "Writeable" to "false" on an attribute
makes the attribute read-only. The default is read-write.
-->

<MBeanType
Name = "SimpleSampleIdentityAsserter"
DisplayName = "SimpleSampleIdentityAsserter"
Package = "examples.security.providers.identityassertion.simple"
Extends = "weblogic.management.security.authentication.IdentityAsserter"
PersistPolicy = "OnUpdate"
>

<!-- You must set the value of the ProviderClassName attribute
(inherited from the weblogic.management.security.Provider mbean)
to the name of the java class you wrote that implements the
weblogic.security.spi.AuthenticationProvider interface.

You can think of the provider's mbean as the factory
for your provider's runtime implementation.
-->
<MBeanAttribute
Name = "ProviderClassName"
Type = "java.lang.String"
Writeable = "false"
Preprocessor = "weblogic.management.configuration.LegalHelper.checkClassName(value)"
Default = "&quot;examples.security.providers.identityassertion.simple.SimpleSampleIdentityAsserterProviderImpl&quot;"
/>

<!-- You must set the value of the Description attribute
(inherited from the weblogic.management.security.Provider mbean)
to a brief description of your provider.
It is displayed in the console.
-->
<MBeanAttribute
Name = "Description"
Type = "java.lang.String"
Writeable = "false"
Default = "&quot;WebLogic Simple Sample Identity Asserter Provider&quot;"
/>

<!-- You must set the value of the Version attribute
(inherited from the weblogic.management.security.Provider mbean)
to your provider's version. There is no required format.
-->
<MBeanAttribute
Name = "Version"
Type = "java.lang.String"
Writeable = "false"
Default = "&quot;1.0&quot;"
/>

<!-- You must set the value of the SupportedTypes attribute
(inherited from the
weblogic.management.security.authentication.IdentityAsserter mbean)
to the list of token types that your identity asserter supports.

Whoever is initiating the identity assertion (eg. a client sending
a perimeter authentication token via an HTTP request header), must
use the same token type.
-->
<MBeanAttribute
Name = "SupportedTypes"
Type = "java.lang.String[]"
Writeable = "false"
Default = "new String[] { &quot;SamplePerimeterAtnToken&quot; }"
/>
<!-- The ActiveTypes attribute (a settable attribute inherited from the
weblogic.management.security.authentication.IdentityAsserter mbean)
contains the subset of your mbean's SupportedTypes that are active
in the realm.

Which way you should default the active types attribute depends
on your token types. The basic rule is that for any token
type, there must only be one identity asserter in the realm with
that token type as an active type. In short, you can only have
one identity asserter turned on for a given type.

If your token types are commonly implemented by other identity
asserters (eg. X509 certificates), then you should not set them
as default active types. Otherwise, it would be very easy for
an administrator to configure an invalid realm where more than
one identity asserter has the same type turned on. Best
practice is that all the identity asserters turn off the type
by default then the administrator manually turns on the
type in one of the identity asserters that support it.
Look at the weblogic.security.spi.IdentityAsserter javadoc
for some standard token types.

On the other hand, if you have a custom token type that no
other identity asserter will ever implement, you may default the
active types attribute to include your token type. If you do,
then the adminstrator doesn't have to manually turn on your token
type.

Since the simple sample identity asserter's token type is very specific
to the sample (instead of a common type like X509), turn on the
token type by default.
-->
<MBeanAttribute
Name = "ActiveTypes"
Type = "java.lang.String[]"
Default = "new String[] { &quot;SamplePerimeterAtnToken&quot; }"
/>

<!-- Add any custom attributes for your provider here.

The simple sample identity asserter does not have any custom attributes.

Note: custom attributes do not appear in the
console in WLS 7.0. Use the admin command line tool
(java weblogic.Admin) to view and set their values.

Refer to the "Developing Security Services" manual
for more info on defining custom attributes.
-->

</MBeanType>



Implementation of Identity Asserter
package examples.security.providers.identityassertion.simple;

import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.AppConfigurationEntry;
import weblogic.management.security.ProviderMBean;
import weblogic.security.service.ContextHandler;
import weblogic.security.spi.AuthenticationProviderV2;
import weblogic.security.spi.IdentityAsserterV2;
import weblogic.security.spi.IdentityAssertionException;
import weblogic.security.spi.PrincipalValidator;
import weblogic.security.spi.SecurityServices;

/**
* The simple sample identity asserter's runtime implementation.
*
* It looks for tokens of type "SamplePerimeterAtnToken"
* whose matching token is an array of bytes containing a
* string in the form "username=someusername".
*
* It extracts the username from the token and stores it
* in a SimpleSampleCallbackHandlerImpl. This is returned to the
* security framework who hands it to the authenticators'
* login modules. The login modules can use a NameCallback
* to retrieve the user name from the simple sample identity
* asserter's callback handler.
*
* Since it is an identity asserter, it must implement
* the weblogic.security.spi.AuthenticationProvider and
* the weblogic.security.spi.IdentityAsserter interfaces.
*
* It can either implement two classes, and use the
* provider implementation as the factory as the
* factory for the identity asserter, or it can implement
* both interfaces in one class. The simple sample identity
* asserter implments both interfaces in one class.
*
* Note: The simple sample identity asserter's mbean's ProviderClassName
* attribute must be set the the name of this class.
*
* @author Copyright (c) 2002 by BEA Systems. All Rights Reserved.
*/
public final class SimpleSampleIdentityAsserterProviderImpl implements AuthenticationProviderV2, IdentityAsserterV2
{
final static private String TOKEN_TYPE = "SamplePerimeterAtnToken"; // the kind of token's we handle
final static private String TOKEN_PREFIX = "username="; // the token contains a string in the form "username=someusername"

private String description; // a description of this provider

/**
* Initialize the simple sample identity asserter.
*
* @param mbean A ProviderMBean that holds the simple sample identity asserter's
* configuration data. This mbean must be an instance of the simple sample
* identity asserter's mbean.
*
* @param services The SecurityServices gives access to the auditor
* so that the provider can to post audit events.
* The simple sample role mapper doesn't use this parameter.
*
* @see SecurityProvider
*/
public void initialize(ProviderMBean mbean, SecurityServices services)
{
System.out.println("SimpleSampleIdentityAsserterProviderImpl.initialize");
SimpleSampleIdentityAsserterMBean myMBean = (SimpleSampleIdentityAsserterMBean)mbean;
description = myMBean.getDescription() + "\n" + myMBean.getVersion();
}

/**
* Get the simple sample identity asserter's description.
*
* @return A String containing a brief description of the simple sample identity asserter.
*
* @see SecurityProvider
*/
public String getDescription()
{
return description;
}

/**
* Shutdown the simple sample identity asserter.
*
* A no-op.
*
* @see SecurityProvider
*/
public void shutdown()
{
System.out.println("SimpleSampleIdentityAsserterProviderImpl.shutdown");
}

/**
* Gets the simple sample identity assertion provider's identity asserter object.
*
* @return The simple sample identity assertion provider's IdentityAsserter object.
*
* @see AuthenticationProvider
*/
public IdentityAsserterV2 getIdentityAsserter()
{
return this;
}

/**
* Assert identity given a token that identifies the user.
*
* @param type A String containing the token type. The simple sample identity
* asserter only supports tokens of type "SamplePerimeterAtnToken".
* Also, the simple sample identity asserter's mbean's "ActiveTypes" attribute
* must be set to "SamplePerimeterAtnToken" (which is done by default
* when the mbean is created).
*
* @param token An Object containing the token that identifies the user.
* The simple sample identity asserter's token must be an array of bytes
* containing a String of the form "username=someusername".
*
* @param handler A ContextHandler object that can optionally
* be used to obtain additional information that may be used in
* asserting the identity. If the caller is unable to provide additional
* information, a null value should be specified. This sample
* ignores the handler.
*
* While, for simplicity, this sample does not validate the
* contents of the token, identity asserters typically should do
* this (to prevent someone from forging a token). For
* example, when using Kerberos, the token may be generated
* and "signed" by a Kerberos server and the identity asserter
* hands the token back to the Kerberos server to get it
* validated. Another example: when asserting identity from
* X509 certificates, then identity asserter should validate the
* certificate - that it hasn't been tampered, that it's been
* signed by a trusted CA, that it hasn't expired or revoked, etc.
*
* @return a CallbackHandler that stores the username from the token.
* The username can only be retrieved from the callback handler by
* passing in a NameCallback. The sample returns an instance of
* its CallbackHandler implementation (SimpleSampleCallbackHandlerImpl).
*
* @throws IdentityAssertionException if another token type is passed
* in or the token doesn't have the correct form.
*/
public CallbackHandler assertIdentity(String type, Object token, ContextHandler context) throws IdentityAssertionException
{
System.out.println("SimpleSampleIdentityAsserterProviderImpl.assertIdentity");
System.out.println("\tType\t\t= " + type);
System.out.println("\tToken\t\t= " + token);

// check the token type
if (!(TOKEN_TYPE.equals(type))) {
String error =
"SimpleSampleIdentityAsserter received unknown token type \"" + type + "\"." +
" Expected " + TOKEN_TYPE;
System.out.println("\tError: " + error);
throw new IdentityAssertionException(error);
}

// make sure the token is an array of bytes
if (!(token instanceof byte[])) {
String error =
"SimpleSampleIdentityAsserter received unknown token class \"" + token.getClass() + "\"." +
" Expected a byte[].";
System.out.println("\tError: " + error);
throw new IdentityAssertionException(error);
}

// convert the array of bytes to a string
byte[] tokenBytes = (byte[])token;
if (tokenBytes == null || tokenBytes.length < 1) {
String error =
"SimpleSampleIdentityAsserter received empty token byte array";
System.out.println("\tError: " + error);
throw new IdentityAssertionException(error);
}

String tokenStr = new String(tokenBytes);

// make sure the string contains "username=someusername
if (!(tokenStr.startsWith(TOKEN_PREFIX))) {
String error =
"SimpleSampleIdentityAsserter received unknown token string \"" + type + "\"." +
" Expected " + TOKEN_PREFIX + "username";
System.out.println("\tError: " + error);
throw new IdentityAssertionException(error);
}

// extract the username from the token
String userName = tokenStr.substring(TOKEN_PREFIX.length());
System.out.println("\tuserName\t= " + userName);

// store it in a callback handler that authenticators can use
// to retrieve the username.
return new SimpleSampleCallbackHandlerImpl(userName);
}

/**
* Return how to call the login module to perform authentication.
*
* @return A null AppConfigurationEntry since the simple sample identity
* asserter is not an authenticator (thus doesn't have a login module).
*/
public AppConfigurationEntry getLoginModuleConfiguration()
{
return null;
}

/**
* Return how to call the login module to complete identity
* assertion (where the identity asserter finds the user name
* and the authenticator puts the user and its groups into the
* subject).
*
* @return A null AppConfigurationEntry since the simple sample identity
* asserter is not an authenticator (thus doesn't have a login module).
*/
public AppConfigurationEntry getAssertionModuleConfiguration()
{
return null;
}

/**
* Return an object that can validate principals (eg. users
* and groups) that this provider puts into the subject.
*
* @return A null PrincipalValidator since the simple sample identity asserter
* is not an authenticator (thus doesn't put principals into the subject).
*/
public PrincipalValidator getPrincipalValidator()
{
return null;
}
}



Implementation of Callback Handler - this is called by LoginModule to obtain username
Callback is registed when LoginModule is created
package examples.security.providers.identityassertion.simple;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

/**
* The simple sample identity asserter's implementation of the
* CallbackHandler interface.
*
* It is used to make the name of the user from the identity
* assertion token available to the authenticators (who, in
* turn, will populate the subject with the user and the user's
* groups).
*
* This class is internal to the simple sample identity asserter.
* It is not a public class.
*
* @author Copyright (c) 2002 by BEA Systems. All Rights Reserved.
*/
/*package*/ class SimpleSampleCallbackHandlerImpl implements CallbackHandler
{
private String userName; // the name of the user from the identity assertion token

/**
* Create a callback handler that stores the user name.
*
* @param user A String containing the name of the user
* from the identity assertion token
*/
/*package*/ SimpleSampleCallbackHandlerImpl(String user)
{
userName = user;
}

/**
* Used by the authenticators' login modules to get the user name
* that the identity asserter extracted from the identity assertion token.
* This name can only be retrieved via a NameCallback.
*
* @param callbacks An array of Callback objects indicating what data
* the login module is trying to extract from this callback handler.
* It must only contain NameCallbacks.
*
* @exception UnsupportedCallbackException thrown if any of the callbacks
* aren't NameCallbacks.
*
* @see CallbackHandler
*/
public void handle(Callback[] callbacks) throws UnsupportedCallbackException
{
// loop over the callbacks
for (int i = 0; i < callbacks.length; i++) {

Callback callback = callbacks[i];

// we only handle NameCallbacks
if (!(callback instanceof NameCallback)) {
throw new UnsupportedCallbackException(callback, "Unrecognized Callback");
}

// send the user name to the name callback:
NameCallback nameCallback = (NameCallback)callback;
nameCallback.setName(userName);
}
}
}



ant build script used to create jar file which has to be copied into $WL_HOME/server/lib/mbeantypes
<project name="Expenselink Build" default="all" basedir=".">
<property name="fileDir" value="test" />

<target name="all" depends="build"/>

<target name="build" depends="clean,build.mdf,build.mjf"/>

<target name="clean">
<delete dir="${fileDir}" failonerror="false"/>
<delete file="SimpleSampleIdentityAsserter.jar" failonerror="false"/>
<echo message="Clean finish" />
</target>

<!-- helper to build an MDF (mbean definition file) -->
<target name="build.mdf">
<java dir="${basedir}" fork="false" classname="weblogic.management.commo.WebLogicMBeanMaker">
<arg line="-files ${fileDir}" />
<arg value="-createStubs" />
<arg line="-MDF SimpleSampleIdentityAsserter.xml" />
</java>
<echo message="Created Supporting Classes" />
</target>

<target name="build.mjf">

<copy todir="${fileDir}" flatten="true">
<fileset dir=".">
<include name="*.java" />
</fileset>
</copy>

<java dir="${basedir}" fork="false" classname="weblogic.management.commo.WebLogicMBeanMaker">
<arg line="-MJF SimpleSampleIdentityAsserter.jar" />
<arg line="-files ${fileDir}" />
</java>
<echo message="Created Mbean Jar" />
</target>

</project>


Copy SimpleSampleIdentityAsserter.jar to WLS home

[dave@dave simple]$ cp  SimpleSampleIdentityAsserter.jar /app/weblogic121/wlserver_12.1/server/lib/mbeantypes/
[dave@dave simple]$



New Identity Asserter must be defined using WLS console in Security Realms/myrealm/Providers/Authentication/


Detail of new Identity Asserter



Client which adds username=dave into HTTP header of request
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import weblogic.utils.encoders.BASE64Encoder;

/**
* This class is a java program that is used to demonstrate
* perimeter authentication / identity assertion.
*
* Normally, the authenticators configured in WLS are
* responsible for authenticating users (eg. checking
* a password). If the user can be authenticated, then
* the authenticators put the user, and the user's groups,
* into the subject. The subject is used later on for
* access checks (authorization).
*
* When using perimeter authentication, someone calling
* WLS is responsible for authenticating the users. A
* token, containing info that identifies the user, is passed
* into WLS. The identity asserter extracts the user name from
* the token and makes it available to the authenticators.
* The authenticators, instead of authenticating the user,
* directly put the user and the user's groups, into the
* subject. Again, the subject is user later on for
* access checks (authorization).
*
* The perimeter authentication sample has the following parts:
*
* - A webapp that has a jsp which requires identity assertion.
* its pages can only be accessed by users or groups whose name
* is "SamplePerimterAtnUsers". The relative URL of this jsp
* to where WLS is running is
* "SamplePerimeterAtnWebApp/SamplePerimeterAtn.jsp".
*
* - A sample identity asserter who handles tokens whose
* type is "SamplePerimterAtnToken". The tokens are arrays
* of bytes containing a string in the form "username=someusername".
*
* - A sample authenticator that automatically creates a group
* named "SamplePerimeterAtnUsers" and the users
* "SamplePerimeterAtnUser1" (who is a member is
* "SamplePerimeterAtnUsers") and "SamplePerimeterAtnUser2"
* (who is not a member of "SamplerPerimeterAtnUsers").
*
* - This client that takes the WLS URL (eg. http://localhost:7001)
* and a user name (eg. SamplePerimeterAtnUser1) on the command line.
* The client addes "SamplePerimeterAtnWebApp/SamplePerimeterAtn.jsp"
* to the WLS URL to get the URL of the sample perimter atn jsp.
*
* This client creates a SamplePerimterAtnToken that contains the
* user name, puts the token in to a HTTP request header, then sends
* a HTTP GET request to the jsp. If the user is a member of the
* SamplePerimeterAtnUsers group, then access is granted to the
* page and its contents are returned. If not, access is denied
* and this client gets a 401 error. When access is granted, the
* jsp prints the subject (that contains the user name and the
* user's groups) into the page it returns and the client prints
* it out.
*
* @author Copyright (c) 2002 by BEA Systems. All Rights Reserved.
*/
public class SamplePerimeterAtnClient
{
// constants for the token type and format.
// must match the kind of tokens the sample identity asserter uses
final static private String TOKEN_TYPE = "SamplePerimeterAtnToken";
final static private String TOKEN_PREFIX = "username=";

/**
* runs the sample perimeter atn client.
*
* @param an array of String that contains the command line
* args sent to this program. It must have exactly two entries.
* The first is the base WLS URL and the second is the user name.
*
* @throws Exception if any errors occur.
*/
public static void main(String[] args) throws Exception
{
// syntax check:
if (args.length != 2) {
System.out.println("Syntax: java SamplePerimeterAtnClient wls_url (eg. http://localhost:7001) username");
System.exit(1);
return;
}

// get the base url and the user name from the command line args
URL base = new URL(args[0]);
String username = args[1];

System.out.println("------------------------------------------------------------");
System.out.println("Testing " + username);
System.out.println("------------------------------------------------------------");

// make the identity assertion token
String token = TOKEN_PREFIX + username;

// base 64 encode it. The webapp container (that is, internal WLS code) will
// base 64 decode the token. The decoded string will be passed to the
// sample identity asserter as an array of bytes.
BASE64Encoder encoder = new BASE64Encoder();
String encodedToken = encoder.encodeBuffer(token.getBytes());

// connect to the SamplePerimeterAtn jsp
URL url = new URL(base, "daveWeb/dave.jsp");
URLConnection connection = url.openConnection();

// put the identity assertion token into the HTTP header
connection.setRequestProperty(TOKEN_TYPE, encodedToken);

// Print out the returned page
BufferedReader in =
new BufferedReader(new InputStreamReader(connection.getInputStream()));

String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}
in.close();

// connect to the SamplePerimeterAtn jsp
url = new URL(base, "daveWeb/AuthenticationSnoop");
connection = url.openConnection();

// put the identity assertion token into the HTTP header
connection.setRequestProperty(TOKEN_TYPE, encodedToken);

// Print out the returned page
in =
new BufferedReader(new InputStreamReader(connection.getInputStream()));

while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}
in.close();
}
}



Web application descriptors with added security definition
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>daveWeb</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>SecuredPages</web-resource-name>
<url-pattern>/</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>&#xA; DaveRole&#xA; </role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-role>
<role-name>
DaveRole
</role-name>
</security-role>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>NoSuchRealm</realm-name>
</login-config>
<servlet>
<description></description>
<display-name>AuthenticationSnoop</display-name>
<servlet-name>AuthenticationSnoop</servlet-name>
<servlet-class>dave.AuthenticationSnoop</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AuthenticationSnoop</servlet-name>
<url-pattern>/AuthenticationSnoop</url-pattern>
</servlet-mapping>
</web-app>


weblogic.xml
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.2/weblogic-web-app.xsd">
<wls:weblogic-version>10.3.4</wls:weblogic-version>
<wls:context-root>daveWeb</wls:context-root>
<wls:security-role-assignment>
<wls:role-name>DaveRole</wls:role-name>
<wls:principal-name>dave</wls:principal-name>
</wls:security-role-assignment>
</wls:weblogic-web-app>




- contains only jsp page and servlet to show user principal
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>Dave</title>
</head>
<body>
<%= weblogic.security.Security.getCurrentSubject() %>
</body>
</html>


package dave;

import java.io.IOException;
import java.io.PrintWriter;

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

/**
* Servlet implementation class AuthenticationSnoop
*/
public class AuthenticationSnoop extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#HttpServlet()
*/
public AuthenticationSnoop() {
super();
// TODO Auto-generated constructor stub
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();

out.println("<HTML><BODY>");

out.println("<H1>This is a password protected resource</H1>");
out.println("<PRE>");
out.println("User Name: " + req.getRemoteUser());
String name = (req.getUserPrincipal() == null) ? null : req
.getUserPrincipal().getName();
out.println("Principal Name: " + name);
out.println("Authentication Type: " + req.getAuthType());
out.println("Is a Manager: " + req.isUserInRole("manager"));
out.println("</PRE>");
out.println("</BODY></HTML>");
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}

}





AdminServer log
SimpleSampleIdentityAsserterProviderImpl.assertIdentity
Type = SamplePerimeterAtnToken
Token = [B@34c31
userName = dave
SimpleSampleIdentityAsserterProviderImpl.assertIdentity
Type = SamplePerimeterAtnToken
Token = [B@1d26b41
userName = dave

Saturday, May 14, 2011

Weblogic Work Manager

Using Work Managers to Optimize Scheduled Work
http://download.oracle.com/docs/cd/E14571_01/web.1111/e13701/self_tuned.htm#i1072698

Timer and Work Manager API (CommonJ) Programmer's Guide for Oracle WebLogic Server
http://download.oracle.com/docs/cd/E14571_01/web.1111/e13733/toc.htm

Tuning Message-Driven Beans
http://download.oracle.com/docs/cd/E14571_01/web.1111/e13814/mdbtuning.htm#i1134848

weblogic-ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-ejb-jar xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-ejb-jar" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-ejb-jar http://xmlns.oracle.com/weblogic/weblogic-ejb-jar/1.2/weblogic-ejb-jar.xsd">
<!--weblogic-version:10.3.4-->
<wls:weblogic-enterprise-bean>
<wls:ejb-name>TestSesssionEJB</wls:ejb-name>
<wls:stateless-session-descriptor/>
<wls:run-as-principal-name>dave</wls:run-as-principal-name>
<wls:dispatch-policy>daveWM</wls:dispatch-policy>
</wls:weblogic-enterprise-bean>
<wls:weblogic-enterprise-bean>
<wls:ejb-name>SesssionJPA2EJB</wls:ejb-name>
<wls:stateless-session-descriptor/>
<wls:run-as-principal-name>dave</wls:run-as-principal-name>
</wls:weblogic-enterprise-bean>

<wls:work-manager>
<wls:name>daveWM</wls:name>

<wls:max-threads-constraint>
<wls:name>MaxThreadsCountFive</wls:name>
<wls:count>5</wls:count>
</wls:max-threads-constraint>
</wls:work-manager>


</wls:weblogic-ejb-jar>



TestSessionEJB
package dave;


import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import javax.transaction.SystemException;

import org.apache.log4j.Logger;

import weblogic.javaee.TransactionTimeoutSeconds;
import weblogic.kernel.ExecuteThread;
import weblogic.transaction.Transaction;
import weblogic.transaction.TransactionHelper;
import weblogic.work.WorkManager;

/**
* Session Bean implementation class TestSesssionEJB
*/
@Stateless(mappedName = "TestSesssionEJB")
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@TransactionTimeoutSeconds(1800)
public class TestSesssionEJB implements TestSesssionEJBRemote, TestSesssionEJBLocal {

static Logger logger = Logger.getLogger(TestSesssionEJB.class.getName());

/**
* Default constructor.
*/
public TestSesssionEJB() {
}



@Override
public String testWorkManager(int maxThreads) {

System.out.println("WorkManager: maxThreads" + maxThreads);

InitialContext ic = null;
try {
ic = new InitialContext();
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

WorkManager wm = ((weblogic.work.ExecuteThread) Thread
.currentThread()).getWorkManager();
String wmName = wm.getName();
int queueDepth = wm.getQueueDepth();
String threadName = Thread.currentThread().getName();
StringBuilder sb = new StringBuilder();
sb.append("## [testWorkManager] executing in WM: " + wmName);
sb.append(" queueDepth=" + queueDepth);
sb.append(" currentThread=" + threadName);
System.out.println(sb);

try {
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


return sb.toString() ;

}



}



Client log
## [testWorkManager] executing in WM: daveWM queueDepth=0 currentThread=[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=0 currentThread=[ACTIVE] ExecuteThread: '18' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=0 currentThread=[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=0 currentThread=[ACTIVE] ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=0 currentThread=[ACTIVE] ExecuteThread: '17' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=0 currentThread=[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=0 currentThread=[ACTIVE] ExecuteThread: '18' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=0 currentThread=[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=0 currentThread=[ACTIVE] ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=1 currentThread=[ACTIVE] ExecuteThread: '17' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=2 currentThread=[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=1 currentThread=[ACTIVE] ExecuteThread: '18' for queue: 'weblogic.kernel.Default (self-tuning)'
WorkManager: maxThreads20
## [testWorkManager] executing in WM: daveWM queueDepth=0 currentThread=[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'






AdminServer log
####<May 15, 2011 9:27:49 AM CEST> <Info> <WorkManager> <dave> <AdminServer> <ExecuteThread: '0' for queue: 'weblogic.socket.Muxer'> <<WLS Kernel>> <> <> <1305444469893> <BEA-002936> <maximum thread constraint MaxThreadsCountFive is reached> 
####<May 15, 2011 9:27:52 AM CEST> <Info> <WorkManager> <dave> <AdminServer> <ExecuteThread: '2' for queue: 'weblogic.socket.Muxer'> <<WLS Kernel>> <> <> <1305444472266> <BEA-002936> <maximum thread constraint MaxThreadsCountFive is reached>
####<May 15, 2011 9:27:54 AM CEST> <Info> <WorkManager> <dave> <AdminServer> <ExecuteThread: '2' for queue: 'weblogic.socket.Muxer'> <<WLS Kernel>> <> <> <1305444474651> <BEA-002936> <maximum thread constraint MaxThreadsCountFive is reached>
####<May 15, 2011 9:27:55 AM CEST> <Info> <WorkManager> <dave> <AdminServer> <ExecuteThread: '1' for queue: 'weblogic.socket.Muxer'> <<WLS Kernel>> <> <> <1305444475790> <BEA-002936> <maximum thread constraint MaxThreadsCountFive is reached>



WLS console - monitoring

Sunday, February 20, 2011

Access JPA2 entitites using Servlet and Session EJB

Introduction to Oracle Enterprise Pack for Eclipse 11g JPA Workbench
http://www.oracle.com/technetwork/articles/cioroianu-eclipse-jpa-084626.html

1.create Eclipse Web project testWeb


2.create Servlet calling Session EJB
package dave;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Servlet implementation class TestJPAServlet
*/
public class TestJPAServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#HttpServlet()
*/
public TestJPAServlet() {
super();
// TODO Auto-generated constructor stub
}


@EJB
SessionJPA2EJBRemote remoteBusinessIntf;


/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

String nameParam = request.getParameter("emp");

Author author = remoteBusinessIntf.findAuthorByName(nameParam);

System.out.println("author " + author);

PrintWriter out = response.getWriter();

out.println("author" + author);

// Books
Set<Book> books = author.getBooks();

for (Book book : books) {
System.out.println("book " + book);
out.println("book" + book);
}
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}

}




3. call servlet using URL composed of testWeb project and Servlet
http://localhost:7001/testWeb/TestJPAServlet?name=dave



[EL Finest]: 2011-02-20 15:15:14.763--ServerSession(10406216)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--End deploying Persistence Unit books; session file:/home/dave/workspace/wls1033/testJPA2/build/classes/_books; state Deployed; factoryCount 1
[EL Finer]: 2011-02-20 15:15:14.763--ServerSession(10406216)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--client acquired
[EL Finer]: 2011-02-20 15:15:14.763--UnitOfWork(25911694)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--TX binding to tx mgr, status=STATUS_ACTIVE
[EL Finest]: 2011-02-20 15:15:14.764--UnitOfWork(25911694)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--Execute query ReadObjectQuery(referenceClass=Author sql="SELECT ID, NAME, INSERT_TIMESTAMP FROM AUTHOR WHERE (ID = ?)")
[EL Finest]: 2011-02-20 15:15:14.764--ServerSession(10406216)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--reconnecting to external connection pool
[EL Fine]: 2011-02-20 15:15:14.765--ServerSession(10406216)--Connection(3587614)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--SELECT ID, NAME, INSERT_TIMESTAMP FROM AUTHOR WHERE (ID = ?)
bind => [1]
[EL Finer]: 2011-02-20 15:15:14.767--UnitOfWork(25911694)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--TX beforeCompletion callback, status=STATUS_ACTIVE
[EL Finer]: 2011-02-20 15:15:14.767--UnitOfWork(25911694)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--begin unit of work commit
[EL Finer]: 2011-02-20 15:15:14.768--UnitOfWork(25911694)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--TX afterCompletion callback, status=COMMITTED
[EL Finer]: 2011-02-20 15:15:14.769--UnitOfWork(25911694)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--end unit of work commit
[EL Finer]: 2011-02-20 15:15:14.769--UnitOfWork(25911694)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--release unit of work
[EL Finer]: 2011-02-20 15:15:14.769--ClientSession(26961217)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--client released
author dave.Author@1fbc274
[EL Finest]: 2011-02-20 15:15:14.77--UnitOfWork(25911694)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--Execute query ReadAllQuery(name="books" referenceClass=Book )
[EL Finest]: 2011-02-20 15:15:14.77--ServerSession(10406216)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--reconnecting to external connection pool
[EL Fine]: 2011-02-20 15:15:14.771--ServerSession(10406216)--Connection(11941411)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--SELECT ID, TITLE, COUNTER, INSERT_TIMESTAMP, AUTHOR_ID FROM BOOK WHERE (AUTHOR_ID = ?)
bind => [1]
[EL Finest]: 2011-02-20 15:15:14.773--UnitOfWork(25911694)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--Execute query ReadObjectQuery(name="author" referenceClass=Author )
[EL Finest]: 2011-02-20 15:15:14.774--UnitOfWork(25911694)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--Register the existing object dave.Book@9c71bf
book dave.Book@9c71bf