3/26/08


J2EE Security with WebLogic 9.2.1 Part 3. Web Services


J2EE Security with WebLogic 9.2.1 Part 2. EJB


Let's consider enterprise bean (EJB 2.1 with WebLogic annotations):

import java.util.Calendar;
import javax.ejb.SessionBean;
import weblogic.ejb.GenericSessionBean;
import weblogic.ejbgen.RemoteMethod;
import weblogic.ejbgen.Session;
import weblogic.ejbgen.JndiName;
import weblogic.ejbgen.FileGeneration;
import weblogic.ejbgen.Constants;
import weblogic.ejbgen.RoleMappings;
import weblogic.ejbgen.RoleMapping;

@Session(ejbName = "MyBean")
@RoleMappings(value={@RoleMapping(principals = "alex", roleName = "admin")})
@JndiName(remote = "ejb.MyBeanRemoteHome")
@FileGeneration(remoteClass = Constants.Bool.TRUE, remoteHome = Constants.Bool.TRUE, localClass = Constants.Bool.FALSE, localHome = Constants.Bool.FALSE)

public class MyBean extends GenericSessionBean implements SessionBean {
private static final long serialVersionUID = 1L;

public void ejbCreate() { }

@RemoteMethod(roles="admin")
public String getDate() {
System.out.println(getSessionContext().getCallerPrincipal().getName());
return "Date from ejb is: " + Calendar.getInstance().getTime().toString();
}
}


Also user alex should be created in Web Logic Server console for default realm. Let's try to invoke that bean from next code:

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, "weblogic");
env.put(Context.SECURITY_CREDENTIALS, "weblogic");
env.put(Context.PROVIDER_URL, "t3://localhost:7001");

Context ct = new InitialContext(env);
Object homeObject = ct.lookup("ejb.MyBeanRemoteHome");
MyBeanRemoteHome home = (MyBeanRemoteHome) PortableRemoteObject.narrow( homeObject, MyBeanRemoteHome.class);
System.out.println(home.create().getDate());


The result is: java.rmi.AccessException: [EJB:010160]Security Violation: User: 'weblogic' has insufficient permission to access EJB...

(Also we can use next code to retrieve Initial Context:
weblogic.jndi.Environment env = new Environment();
env.setProviderUrl("t3://localhost:7001");
env.setInitialContextFactory("weblogic.jndi.WLInitialContextFactory");
env.setSecurityPrincipal("alex");
env.setSecurityCredentials( "weblogic");
javax.naming.InitialContext ct = new InitialContext(env.getInitialContext().getEnvironment());)

Let's replace env.put(Context.SECURITY_PRINCIPAL, "weblogic") to env.put(Context.SECURITY_PRINCIPAL, "alex"). The result is Ok.

Let's do:

//env.put(Context.SECURITY_PRINCIPAL, "alex");
//env.put(Context.SECURITY_CREDENTIALS, "weblogic");

The result is: Security Violation: User: 'anonymous' has insufficient permission to access EJB..

Let's use JAAS:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.PrivilegedAction;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.security.auth.login.*;
import com.MyBeanRemoteHome;
import weblogic.security.Security;

public class Main {
public static void main(String[] args) throws Exception {
LoginContext loginContext = null;
loginContext = new LoginContext("Sample", new SampleCallbackHandler("alex", "weblogic", "t3://localhost:7001"));
loginContext.login();
Security.runAs(loginContext.getSubject(), new EjbInvocation());
return;
}

public static class EjbInvocation implements PrivilegedAction {
public Object run() {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL, "t3://localhost:7001");
Context ct = new InitialContext(env);
Object homeObject = ct.lookup("ejb.MyBeanRemoteHome");
MyBeanRemoteHome home = (MyBeanRemoteHome) PortableRemoteObject.narrow( homeObject, MyBeanRemoteHome.class);
System.out.println(home.create().getDate());
return null;
}
}
}


Now it's okay too.

Next part of research is accessing EJB from secured servlet described in previous post. Servlet and EJB belong to one Realm. Servlet just contain code in service method:

Hashtable env = new Hashtable();
env.putContext.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL, "t3://localhost:7001");
Object homeObject = new InitialContext(env).lookup("ejb.MyBeanRemoteHome");
MyBeanRemoteHome home = (MyBeanRemoteHome) PortableRemoteObject.narrow(homeObject, MyBeanRemoteHome.class);
home.create().getDate();

So access to that sarvlet can be done only by authenticated user. Let's try to access as weblogic user. Result is: Security Violation: User: 'weblogic' has insufficient permission to access EJB:..
Nice! Next login as alex user. Result is Ok (ejb method returned string successfuly). Great. Servlet accesseb EJB with account of user that has been invoking the servlet.

J2EE Security with WebLogic 9.2.1 Part 1. Web


First of all let us look into web application sequrity. Suppose we have some .war file with servlet com.MyServlet and web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<display-name>Investigation_web</display-name>
<servlet>
<description></description>
<display-name>MyServlet</display-name>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.MyServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<security-role>
<description>This is the boss</description>
<role-name>manager</role-name>

</security-role>

<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
</web-resource-collection>

<auth-constraint>
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>

<login-config>
<auth-method>FORM</auth-method>
<realm-name>Example Form-Based Authentication Area</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login.jsp</form-error-page>
</form-login-config>
</login-config>

</web-app>

Also weblogic.xml contains:

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wls="http://www.bea.com/ns/weblogic/90" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-web-app.xsd">
<wls:context-root>Investigation_web</wls:context-root>
<wls:security-role-assignment>
<wls:role-name>manager</wls:role-name>
<wls:principal-name>alex</wls:principal-name>
</wls:security-role-assignment>
</wls:weblogic-web-app>


And in WebLogic Server console of our Domain we created user alex in default Realm. And finally there is login.jsp:

<form method="POST" action="j_security_check">
Username: <input type="text" value="weblogic" name="j_username"><br />
Password: <input type="password" value="weblogic" name="j_password"><br />
<br />
<input type="submit" value="Login">
<input type="reset" value="Reset">

</form>

So if user try to access MyServlet or any other resource that meets <url-pattern>/*</url-pattern> he will be redirected into login page. Also if use <auth-method>BASIC</auth-method> then no jsp login page is needed instead will be used popup window from your browser.
It is clear but what if we will try to acess URL in java standalone application's code? First of all I consider possibility of using HttpURLConnection as described in previous post of my blog. In that case we can fulfil:
1-request to login page and accept cookie;
2-post form with parameter names that we can find in login page HTML source (usual: username and password) with cookie;
3-request desired resource with cookie.

But it not seems the solution is simple. There is also Authenticator class to do similar job:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;

public class Main {


public static void main(String[] args) throws IOException {
Authenticator.setDefault(new SimpleAuthenticator("alex", "password"));
URL myUrl = new URL("http://localhost:7001/Investigation_web/MyServlet");
HttpURLConnection yc = (HttpURLConnection)myUrl.openConnection();
yc.setDoInput(true);
yc.setDoOutput(true);
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}


public static class SimpleAuthenticator extends Authenticator {
private String username;
private String password;
public SimpleAuthenticator(String username, String password) {
this.username = username;
this.password = password; }
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
}
}


But it approach useful only in case of BASIC auth-method. It is called "authenticate using the digest method". Might be we can use JAAS functionality? Pay attention that to run this code on Java 1.5 you have to add file sample_jaas.config that contains:

/** Login Configuration for the JAAS Sample Application **/
Sample { weblogic.security.auth.login.UsernamePasswordLoginModule required debug=false;};


and add line to java.security:

login.config.url.1=file:${java.home}/lib/security/sample_jaas.config

all those in directory: JAVA_HOME\jre\lib\security.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.PrivilegedAction;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.security.auth.login.*;
import com.MyBeanRemoteHome;
import weblogic.security.Security;


public class Main {

public static void main(String[] args) throws Exception {
LoginContext loginContext = null;
loginContext = new LoginContext("Sample", new SampleCallbackHandler("alex", "weblogic", "t3://localhost:7001"));
loginContext.login();
Security.runAs(loginContext.getSubject(), new WebInvocation());
return;
}
public static class WebInvocation implements PrivilegedAction {
public Object run() {
URL myUrl;
try {
myUrl = new URL("http://localhost:7001/Investigation_web/MyServlet");
HttpURLConnection yc = null;
yc = (HttpURLConnection) myUrl.openConnection();
yc.setDoInput(true);
yc.setDoOutput(true);
BufferedReader in = new BufferedReader(new InputStreamReader(yc
.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}


No.. result is the same - we recieve redirect to login page in case of FORM auth-method and "Response: 401: Unauthorized" for BASIC. What about authenticate with certificates? For now nothing ). There is also question about why code to logout user:

request.getSession().invalidate();

does not work in case of BASIC authentication..

Next let's look into using URLConnection from some secured servlet to it themselves. Result of such invoking is the same as from standalone client: so in case of FORM authentication method request redirected to login page and in case of BASIC authentication method Response: '401: Unauthorized'. So the fact that invoking of some URL is doing from already authenticated code does not matter at all. The code have to tranfer cookie explicitly or use another method to authetication (Authenticator class and probably others). What about using url appending instead cookie? For now nothing again)

3/25/08


Servlets invoking by java standalone (form posting)


Sometimes we have to do access to URL resource or in particular invoke some servlet (via HTTP protocol). There is some different approaches to invocation via HTTP protocol: through GET or through POST. GET request is pretty simple to realize. Just put next code:

String url = http://localhost/AppWeb/myServlet?param1=val1&param2=val2";
URLConnection uc = new URL(url).openConnection();
uc.setDoOutput(true);
uc.setDoInput(true);
//TO DO #1 some code put here to sign request as POST
InputStream istr = uc.getInputStream();
//TO DO #2 something do with respond (istr)


Differences (rather similarities) between URLConnection and HttpURLConnection can be shown in next lines:

URL url = new URL(urlString);
URLConnection connection = url.openConnection();
if (connection instanceof HttpURLConnection) {
HttpURLConnection httpConnection = (HttpURLConnection)connection;
}

Servlet (myServlet) will accept request from first source as GET method. In "TO DO #2" just do something with servlet's respond. In case of HttpURLConnection it is possible to retrieve response code and message: httpConnection.getResponseCode(); or httpConnection.getResponseMessage() .
It is possible to put next code instead "TO DO #1" to convert that request into POST request:

BufferedWriter wr = new BufferedWriter(new PrintWriter(uc.getOutputStream()));
wr.write("param3=val3&"); //PAY ATTENTION. SYMBOL > & < param4="val4">
Just we fulfil some writing into body of our connection, connection become POST request. There are some difficulties with file adding to POST request from java application and treatment those files in servlets. Firstly, for simple html form posting with file fild, form has to be multipart/form-data (enctype) and there is method setRequestProperty(key, value) in our URLConnection to set these property in java code like by html tags:

<form enctype="multipart/form-data" action="DownWithAPI" method="POST">
<input type="file" name="filetoupload" />
<input type="submit" value="Go" />
</form>


Secondly we need not write some parameters manualy. Instead we can use some simple API (one java file): ClientHttpRequest 1.4 or ClientHttpRequest 1.0. Using is pretty simple too:

String url = http://localhost/AppWeb/myServlet?param1=val1&param2=val2";
ClientHttpRequest client = new ClientHttpRequest(url);
client.setParameter("file", new File("d:/dome.txt"));
client.setParameter("param5", "value5");
client.post().read();


Now look into more difficult part of work - treatment our request on server side (in servlet). Pay attention that servlet deals with post request in doPost method. Transmitted parameters in both case can be retrieved via HttpServletRequest parameter (in doGet or doPost) in manner:

String dataFromClient = request.getParameter("param1");

But in case of multipart/form-data that approach is not useful. Instead we need to parse request.getInputStream() as multipart container. To do this I suggest to use API again: form-data Reader in manner:

Map map = MultipartFormReader.read(request);
String value1= map.get("SomeParamName1").toString();
byte[] file =((DataSource) map.get("fileParam1")).getBinaryContent();
String value2 = map.get("SomeParamName1").toString();

All keys can be retrieved via:

Map map = MultipartFormReader.read(request);
Iterator it = map.keySet().iterator();
while(it.hasNext()){
System.out.println(it.next().toString());
}


And also I will talk about downloading with servlet functionality. Method below can clarify this situation:

private void doDownload(HttpServletRequest req, HttpServletResponse resp, String original_filename, InputStream istr){
ServletOutputStream op = resp.getOutputStream();
resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition", "attachment; filename=\"" + original_filename + "\"");
byte[] b = new byte[8164];
int len = 0;
int fullLen = 0;
while ((len = istr.read(b, 0, 8164)) != -1){
op.write(b, 0, len);
fullLen = fullLen + len;
}
resp.setContentLength(fullLen);
istr.close();
op.flush();
op.close();
}


Just put him some InputStream (from file for example or byte array stream). After and before invoking of that method do not invoke any response.getWriter().write(" "); because it will be Exception throwing.

There are some interesting issue in working with java.net.URLConnection or
HttpURLConnection. For example it is posible to set some usefull properties:

String url = http://localhost:8080/MyJavaServer_web/Down;
HttpURLConnection hconn = (HttpURLConnection) new URL(url).openConnection();


hconn.setDoInput(true);
hconn.setDoOutput(true);

hconn.setRequestMethod("POST");

hconn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461)");

conn.setRequestProperty("Accept", "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
conn.setRequestProperty("Accept-Language","de-de,de;q=0.8,en-us;q=0.5,en;q=0.3");
conn.setRequestProperty( "Accept-Encoding","gzip,deflate");
conn.setRequestProperty( "Accept-Charset","ISO-8859-1,utf-8;q=0.7,*;q=0.7");
conn.setRequestProperty( "Keep-Alive","300");
conn.setRequestProperty( "Proxy-Connection","keep-alive");
conn.setRequestProperty( "Cache-Control","max-age=0");

conn.setConnectTimeout(5000);

wr.flush();


After flushing servlet Down will accept POST request from .. Mozilla.
There is also posibility to set up cookie in the reques:

String cookie = null;
hconn.setRequestProperty("Cookie", cookie);

As you can see "Cookie" in transmitted while web request as plain string. Those string can be retrieved after first request to the server in code:

cookie = hconn.getHeaderField("Set-Cookie");

Pay attention that if server accepts request with "Cookie" property it will not fulfil "Set-Cookie" in response and hconn.getHeaderField("Set-Cookie") will be null.
For using proxy put next code before invoking openConnection() for URL:

Properties systemProperties = System.getProperties();
systemProperties.setProperty("http.proxyHost",proxy);
systemProperties.setProperty("http.proxyPort",port); //And optionally:
System.setProperty("http.proxyUser", "");
System.setProperty("http.proxyPassword", "");

And finally for authentication create simple class:

public class SimpleAuthenticator extends Authenticator{
private String username;
private String password;
public SimpleAuthenticator(String username,String password) {
this.username = username;
this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication( username,password.toCharArray());
}
}

And before creating new URL (URL myUrl= new URL(url);) invoke:

Authenticator.setDefault(new SimpleAuthenticator(username, password));

The end.

3/13/08


Linux forever or dead-end road


I installed Linux Ubuntu 10.4 about two weeks ago.
Firs impressions was very positive. I have some experience with Linux in the past. But it did not meter for now :). I was not able to do any thing except invoke some pre installed application, especially game.
I had some success after two days with help of my friend KirGiz. I have got pretty good speed of system loading, have installed midnight commander :), arena 3 and even new version of JDK and Eclipe Europa (Thanks to Stas also). It was greate. Also I have installed my ATI video card and XGL engine. I did not gain success with "cube desktop" but other nice visual effects was presented. By the the time I bored with all those beauty and even thought that Ubuntu was not good place for me. But.
I returned to research my laptop's Linux couple of days ago. It was related to recent c++ programming under the DOS in Borland c++ 3. When only keyboard was used. First af all I switched off my Gnome XConsole (with rcconf) and find myself in Linux command line interface. After couple of hours I find real beauty and real satisfaction. It was so suddenly that I am fall in love with this OS. I even used lynx. It was very strange experience but cool also. Only command prompt and you. Without any visual unusuall most of time widgets. Only couple of terminals. It is inconvenient for first time but regular operation will be very fast in due course.
There are much programms for console mode, for example audio player. I hope I will find some Java IDE for terminal.
Some usefull commands:
- gedit // Text Editor (GUI)
- dav // Text Editor (console)
- lynx // Web Browser (console) G - addres; O - config; Q - quit; / - page source; [Del] - list of visited addresses.
- rcconf // boot options
- touch Par1 //creates empty file with name as Par1. e.g. /fastboot or /forcefsck
Some interesting locations:
- /etc/fstab

Titanic just wanted to be submarine

Open source or warranty of support?

I met with some problem with WebLogic 9.2 last week.

I am using WebLogic 9.2 sp1 + AquaLogic 2.6 last time. I have created EJB (2.1 right from WLW) with some methods that throws Exceptions. I have tried to create transport typed business service (BS) for my EJB. When I looked into WSDL for that BS I did not find soap faults description for my methods. I sent request to BEA and got response with clarification and patch Id for resolve that problem :)
I installed that patch with Smart Update and it seemed was all okay then. I found SOAP fault block in my WSDL. But.
I tried to fulfil simple code on the patched serverside:

Hashtable h = new Hashtable();
h.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
h.put(Context.PROVIDER_URL, "t3://localhost:7002");
h.put(Context.SECURITY_PRINCIPAL, "weblogic");
h.put(Context.SECURITY_CREDENTIALS, "weblogic");
InitialContext inc = new InitialContext(h);

Pay attention that I looked up Initial Context in web application running on the "9.2 SP1 WebLogic Server with patched ALSB" to "8.1 "WebLogic Server"!

I have got Exception:

java.lang.AssertionError: java.lang.ClassNotFoundException: weblogic.jndi.internal.ServerNamingNode_920_WLStubat weblogic.jndi.WLInitialContextFactoryDelegate.newRootNamingNodeStub(WLInitialContextFactoryDelegate.java:587)at weblogic.jndi.WLInitialContextFactoryDelegate.newRemoteContext(WLInitialContextFactoryDelegate.java:559)
....

I had question: "Why Class Loader tries to find ServerNamingNode_920_WLStubat instead of ServerNamingNode_921_WLStubat". I started investigate that problem couple of days ago. I know reason now. But I have spent about a week for that problem :(

First of all I found line in my %WLS_HOME%\common\bin\commEnv.cmd
set PATCH_CLASSPATH=%WLS_HOME%\profiles\default\sys_manifest_classpath\weblogic_patch.jar

Pay attention that PATCH_CLASSPATH got the first place in domain claspath!
That was Jar was installed with patch. By going through chain from that Jar (by manifest Class-Path:... ) I found another Jar. It contains manifest file:

Manifest-Version: 1.0
Created-By: 1.5.0_03 (Sun Microsystems Inc.)
Implementation-Title: AquaLogic Service Bus 2.6 Patch for CR311833
Implementation-Version: 9.2
Implementation-Vendor: BEA Systems

Next I decompiled some chain of weblogic.jar classes (first was WLInitialContextFactoryDelegate) with JAD and have strange result:

------------------------------------------

WLInitialContextFactoryDelegate:
private NamingNode newRootNamingNodeStub(RemoteReference remotereference, int i)
{

...
Class class1 = Class.forName(RootNamingNode.STUB_NAME);

...
}


------------------------------------------

RootNamingNode:
STUB_NAME = ServerHelper.getStubClassName((weblogic.jndi.internal.ServerNamingNode.class).getName());

------------------------------------------

ServerHelper:
public static String getStubClassName(String s)
{
return s + WLS_STUB_VERSION;
}

....
public static final String WLS_STUB_VERSION = "_" + PeerInfo.getPeerInfo().getMajor() + PeerInfo.getPeerInfo().getMinor() + PeerInfo.getPeerInfo().getServicePack() + "_WLStub";

------------------------------------------

PeerInfo:
public static PeerInfo getPeerInfo()
{
return singleton;
}


...

VersionInfo versioninfo = VersionInfo.theOne();
singleton = new PeerInfo(versioninfo.getMajor(), versioninfo.getMinor(), versioninfo.getServicePack(), versioninfo.getRollingPatch(), versioninfo.hasTemporaryPatch(), versioninfo.getPackages());


------------------------------------------

VersionInfo:
public static VersionInfo theOne()
{
return Maker.THE_ONE;
}


...

public final int getServicePack()
{
return servicePack;
}
...
public VersionInfo(boolean flag) throws VersioningError
{

...
packages = getLocalWLPackages();
...

implVendor = packages[0].getImplementationVendor();
implTitle = packages[0].getImplementationTitle();
implVersion = packages[0].getImplementationVersion();
major = packages[0].getMajor();
minor = packages[0].getMinor();
servicePack = packages[0].getServicePack();
...
}


------------------------------------------

Maker:
static final VersionInfo THE_ONE = VersionInfo.access$000() ? new VersionInfo(true) : new VersionInfo(9, 2, 1, 0);

------------------------------------------

There are another constructors in the VersionInfo class but it is clear that for some reason in case of my web application constructor VersionInfo(true) was invoked in runtime.

So as you can see WebLogic gets its version information from ... manifest of the Jar file that placed first in the CLASSPATH!!!! As you remember first Jar file is my patche's Jar with:
Implementation-Version: 9.2
It does not contain version of SP. So WebLogic after patch of AquaLogic does not know about its SP version!
Now I can change order of my Jar in the server CLASSPATH or ... change line:
Implementation-Version: 9.2
to
Implementation-Version: 9.2.1
Both cases are work. I have tested.

The engineer form BEA support said me about those code:

"Well yes, that's true, but you see that the problem is coming from the patch that you install the first time, I guess if the patch was the correct one of the WLS installation , every thing will work fine, but since the patch was not well installed let say, it's logic that nothing will work, for me."

Nevertheless I have one question: why BEA WebLogic AS that able to do anything (almost anything) and costs so much money retrieve version info about itself by using logic:

...

packages = getLocalWLPackages(); //All WebLogic AquaLogic packages in CP

servicePack = packages[0].getServicePack(); //First off all

...

It seems like Titanic 9.2 is the ship until it have gotten some screws from submarine. Just it happens the same time it considered whole itself as submarine :). There is no reason to explain result of that misunderstanding. LOL.


http://forums.bea.com/thread.jspa?threadID=5700000130

http://forums.bea.com/forum.jspa?forumID=2057

3/6/08


English Learning: Dictionary + Trainer

Today I shown my Top Dictionary (also known as Top Editor) to Thor:


So I think it is time to show my product here also. It was long way from my first simple HTML-based english trainer. I have made it on c++, php and C#. But always idea was prety identical - if you want to study English - you need partner. Exactly such e-partner I have been trying to implements a lot of years. May be name "partner" is too loude but anyway it is prety usefull tool. I hope it will be better in future.
Main futures:
- usefull editing studied words;
- management by samples for those words;
- ability to record sound for a words and samples;
- presence of trainer;
- easy printing all wards in paper;
- easy play sounds in any mp3-player;

BEA forever

Yesterday I posted request to BEA customer support. Today I have received full description of the possble decision. Thanks a lot. It was my first request to official support and successfull. Also I have respond on BEA forum. Great

3/4/08


There is xsd inheritance!

Look into two classes:

package com;
public class SomeBase {
}


package com;
public class SomeChild extends SomeBase {
}


and result conversion into xsd:

<xs:complexType name="SomeChild">
<xs:complexContent>
<xs:extension base="java:SomeBase" xmlns:java="java:com"/>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="SomeBase"/>

Some incomprehension

I have found some xsd definition:

<xs:schema targetNamespace="java:java.lang" xmlns:xs=http://www.w3.org/2001/XMLSchema>
<xs:complexType name="NullPointerException">
<xs:complexContent>
<xs:extension base="java:RuntimeException" xmlns:java="java:java.lang"/>
</xs:complexContent>

</xs:complexType>
<xs:complexType name="RuntimeException"/>

</xs:schema>

My attention is attracted by line <xs:extension base="... Is there inheritance in XML Schema?

-------------------------------------------------------------

Another strange issue. Let's look into my MyException src:

package com;
public class MyException extends java.lang.Exception {
private static final long serialVersionUID = 6543L;
private java.lang.String myException;

public java.lang.String getMyException() { return this.myException; }
public MyException() { }

public MyException(java.lang.String myException) { this.myException = myException; }

// public MyException(Throwable ex) {

// super(ex);
// }
}

In WSDL for my service it appears as:

<xs:complexType name="MyException">
<xs:sequence>

<xs:element minOccurs="1" name="MyException" nillable="true" type="xs:string"/>
</xs:sequence>

</xs:complexType>
<xs:element name="MyException" type="java:MyException" xmlns:java="java:com"/>


But clientgen generates right definition for class MyException (with extends). From where it know about if in WSDL information is absence?

-------------------------------------------------------------

Next incomprehension tied with comment code in my Exception class. If uncomment those lines then web service invocation will be accompanied with:

weblogic.wsee.codec.CodecException: Failed to encode
at weblogic.wsee.codec.soap11.SoapCodec.encodeFault(SoapCodec.java:362)...

-----------------------------------------------------

JNDI
I have deployed EJB on the WebLogic server. It has jndi:

EJB is allocated in EAR project:First question:
I looked up that EJB via:

context.lookup("ejb.ScfBeanRemoteHome");

EAR project name not needs while jndi lookup???

Second:
I listed all context containig by:

NamingEnumeration en = context.list("");

while(en.hasMore())
{
System.out.println(en.next().toString());
}


and did not find "ejb.ScfBeanRemoteHome" name.. Why? Where is that name?

List:
com_bea_wli_monitoring_alert_AlertLogService: com.bea.wli.monitoring.alert.AlertLoggerImpl
mejbmejb_jarMejb_EO: weblogic.rmi.cluster.ClusterableRemoteObject
ejb: weblogic.jndi.internal.ServerNamingNode
ALSB Test FrameworksbTestFwkEjb_jarTestService_EO: weblogic.rmi.cluster.ClusterableRemoteObject
com_bea_wli_monitoring_Aggregator: com.bea.wli.monitoring.statistics.prototype.ClusterAggregatorImpl
QueueIn: weblogic.jms.common.WrappedDestinationImpl
javax: weblogic.jndi.internal.ServerNamingNode
wli: weblogic.jndi.internal.ServerNamingNode
ScfEjbMediator_ear: weblogic.jndi.internal.ServerNamingNode
wlsbjmsrpDataSource: weblogic.rmi.cluster.ClusterableRemoteObject
AdminServer_clusterTimerAuthority: com.bea.wli.timer.ClusterTimerAuthorityImpl
weblogic: weblogic.jndi.internal.ServerNamingNode
bea_wls_remote_deployerbea_wls_remote_deployer_jarDeployerBean_EO: weblogic.rmi.cluster.ClusterableRemoteObject
ScfEjbMediator_earScfEjbMediator_ejb_jarScfBean_EO: weblogic.rmi.cluster.ClusterableRemoteObject
ScfEjbMediator_earScfEjbMediator_ejb_jarUtiliteBean_EO: weblogic.rmi.cluster.ClusterableRemoteObject
wlsb: weblogic.jndi.internal.ServerNamingNode
ServiceBus_Console: weblogic.jndi.internal.ServerNamingNode
com: weblogic.jndi.internal.ServerNamingNode
WebLogicEJB_ejbWebLogicEJB_ejbSomeEjb_EO: weblogic.rmi.cluster.ClusterableRemoteObject

Weblogic Service Bus service generation


Some unexpected behaviour was trailed when business Transport Typed Service generated. My EJB looks like:


@RemoteMethod
public String someMethod(String arg) {

return "Hello " + arg;
}
@RemoteMethod
public String someMethod2(String arg) throws MyException {
throw new MyException("ERR");
//return "Hello " + arg;
}


but if I generate business service by EJBClientJar of that EJB I do not find fault part in operation description for second method in the its WSDL. Moreover I do not find MyException type definition as well:

<s0:operation name="someMethod2">
<s2:operation soapAction="http://www.openuri.org/someMethod2
" style="document"/>
<s0:input>
<s2:body parts="parameters" use="literal"/>
</s0:input>
<s0:output>
<s2:body parts="parameters" use="literal"/>
</s0:output>
</s0:operation>


http://forums.bea.com/thread.jspa?threadID=300006140

Web services exceptions handling


There are two web methods in previous topic. Each of them throws exception:
RuntimeException and checked exception com.MyException

In second case wsdl description has fault description part:

<s0:operation name="meth2Checked">
<s3:operation soapAction="" style="document"/>
<s0:input>
<s3:body parts="parameters" use="literal"/>
</s0:input>
<s0:output>
<s3:body use="literal"/>
</s0:output>
<s0:fault name="MyException">
<s3:fault name="MyException" use="literal"/>
</s0:fault>


So JAX-RPC stubs has exception description in signature of the correspondent methods.
If involkes such methods:

Exception in thread "main" com.MyException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)....


In case of throwing RuntimeException we just have in runtime:

Exception in thread "main" java.rmi.RemoteException: SOAPFaultException - FaultCode [{http://schemas.xmlsoap.org/soap/envelope/}Server] FaultString [Failed to invoke end componentFailed to invoke method >> RUN TIME EXCEPTION << ] FaultActor [null] Detail [<detail><bea_fault:stacktrace xmlns:bea_fault=http://www.bea.com/servers/wls70/webservice/fault/1.0.0>java.lang.RuntimeException: >> RUN TIME EXCEPTION <<
at com.ErrWs.meth1RunTime(ErrWs.java:10)
at jrockit.reflect.VirtualNativeMethodInvoker.invoke(Ljava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object;(Unknown Source)
at java.lang.reflect.Method.invoke(Ljava.lang.Object;[Ljava.lang.Object;I)Ljava.lang.Object;(Unknown Source)
....


In case of some transport problem (e.g. absent WS in the defined location) is gotten:

Exception in thread "main" java.rmi.RemoteException: SOAPFaultException - FaultCode [{http://schemas.xmlsoap.org/soap/envelope/}Server] FaultString [Failed to receive message java.io.IOException: The server at http://localhost:7001/WebService_ws/ErrWs returned a 404 error code (Not Found). Please ensure that your URL is correct, and the web service has deployed without error.The server at http://localhost:7001/WebService_ws/ErrWs returned a 404 error code (Not Found). Please ensure that your URL is correct, and the web service has deployed without error.] FaultActor [null] Detail [java.io.IOException: The server at http://localhost:7001/WebService_ws/ErrWs returned a 404 error code (Not Found). Please ensure that your URL is correct, and the web service has deployed without error....

Webogic Web Services invocation

Let's look into some WebLogic WebService:

import javax.jws.*;
@WebServicepublic class ErrWs {
@WebMethod

public void meth1RunTime() {
throw new RuntimeException(" >> RUN TIME EXCEPTION << ");
}

@WebMethod
public void meth2Checked() throws MyException {
throw new MyException(" >> MyException EXCEPTION << ");
}
}

How we can use that web service in java code? First of all use jwsc ant task to genrate JAX-RPC code for that web service:

<taskdef name="jwsc"
classname="weblogic.wsee.tools.anttasks.JwscTask">
<classpath refid="..." />
</taskdef>

<jwsc srcdir="src" destdir="${somedir-dir}">
<jws file="com/ws/ErrWs.java">
</jws>
</jwsc>

In case of some WebLogic web application we can generate web service control but for standalone application (or non WebLogic web application) we need use ClientGenTask. But there is some strange behaviour I meet with..
Below content of my ant build.xml:

< project
default="wsc_lient_gen"
name="LocalClient">
< path id="wl_cp">
< pathelement path="lib/weblogic.jar">
< pathelement path="lib/xbean.jar">
< pathelement path="lib/apache_xbean.jar">
< pathelement path="lib/webserviceclient.jar">
</path>
<taskdef

name="clientgen"
classpathref="wl_cp"
classname="weblogic.wsee.tools.anttasks.ClientGenTask">
</taskdef >
<target name="wsc_lient_gen">
<clientgen

classpathref="wl_cp"
wsdl=http://localhost:7001/WebService_ws/ErrWs?WSDL
destdir="gen">
</target>
</project>


But there is exception while run that code right in Eclipse environment:

Buildfile: D:\Screwfix\ErrAttempts_java2\Test\build.xml
wsc_lient_gen:
Generating client from http://localhost:7001/WebService_ws/ErrWs?WSDL ...
[clientgen] Package name is com
[clientgen] DestDir is D:\Screwfix\ErrAttempts_java2\Test\gen
[clientgen] class name is ErrWs_Stub
[clientgen] service class name is ErrWsService
[clientgen] Porttype name is ErrWs
[clientgen] service impl name is ErrWsService_Impl
BUILD FAILED
java.lang.AssertionError: java.io.IOException
Total time: 3 seconds


But in CLI, if before invoking set domain environment:

> %SOME_WL_DOMAIN_PATH%\bin\setDomainEnv.cmd
> ant
all artifacts are generated successfully.

After those operation we need some client's code to invoke web service: (and also 4 *.jar in classpath presented in ant's build file)

ErrWsService service = new ErrWsService_Impl();
ErrWs port = service.getErrWsSoapPort();
port.meth1RunTime();

3/3/08


WebLogic EJB invocation


If you have Ejb Client Jar: (code needs weblogic.jar and Client Jar for yours EJB) :

import java.rmi.RemoteException;
import java.util.Hashtable;
import javax.ejb.CreateException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import com.epam.ejb.SomeEjbRemoteHome;

public class Main {
public static void main(String[] args) throws NamingException, RemoteException, CreateException{
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, "weblogic");
env.put(Context.SECURITY_CREDENTIALS, "weblogic");
env.put(Context.PROVIDER_URL,"t3://localhost:7001/Errors_ejb");
Context context = new InitialContext(env);
Object homeObject = context.lookup("ejb.SomeEjbRemoteHome");
SomeEjbRemoteHome home = (SomeEjbRemoteHome)PortableRemoteObject.narrow(homeObject, SomeEjbRemoteHome.class);
home.create().someMethod("some string");
}
}


There is also abiliti to invoke as simple class (needs to have Ejb Class in classpath)

import com.epam.ejb.MyException;
import com.epam.ejb.SomeEjb;
public class Main {
public static void main(String[] args) throws MyException {

SomeEjb ejb = new SomeEjb();
System.out.println(ejb.someMethod("555"));
}
}