Cross Column

Showing posts with label Oracle WebLogic Server. Show all posts
Showing posts with label Oracle WebLogic Server. Show all posts

Sunday, August 23, 2020

Parsing WebLogic Access Log with Perl

Why Perl?


Perl is a general-purpose programming language originally developed for text manipulation and now used for a wide range of tasks including system administration, web development, network programming, GUI development, and more.

Perl is easy, nearly unlimited, mostly fast, and kind of ugly.  However, its power and quickness of coding can also be achieved with the combination of other tools:
  • shell or awk programming with
    • grep, cut, sort, and sed

Access Log in WebLogic


By default, WebLogic Server (WLS) keeps a log of all HTTP transactions in a text file. The file is named access.log and is located in the 
$DOMAIN_HOME/servers/Xxx/logs 
directory.

The log provides true timing information from WebLogic, in terms of how long each individual application request takes. This timing information can be important in troubleshooting a slow system.

For more details, read [2] or other more updated information at the Oracle official site.

Case Study


In this article, we will use the below sample access log entry for the illustration:

2020-08-23      15:54:02        0.031   479     GET     /xx-contentyyyyyyy/api/v1/instances/bootstrap/artifacts/namespaces/content:catalog/attributes/system/skins/activetheme        404     "4cb1bd49-1deb-4b6f-84c5-1153f22e3739-0000000c" "1.4cb1bd49-1deb-4b6f-84c5-1153f22e3739-0000000c;kXKwo3hCQtRLGmjE0ZJOoOTLkKPOoLRKlSODoITT_G"  -       -


Notice that the above fields are separated by horizontal tab (i.e., ht), not spaces.

0000000   2   0   2   0   -   0   8   -   2   3  ht   1   5   :   5   4
0000020   :   0   2  ht   0   .   0   3   1  ht   4   7   9  ht   G   E
0000040   T  ht   /   b   i   -   c   o   n   t   e   n   t   s   t   o
0000060   r   a   g   e   /   a   p   i   /   v   1   /   i   n   s   t
0000100   a   n   c   e   s   /   b   o   o   t   s   t   r   a   p   /
0000120   a   r   t   i   f   a   c   t   s   /   n   a   m   e   s   p
0000140   a   c   e   s   /   c   o   n   t   e   n   t   :   c   a   t
0000160   a   l   o   g   /   a   t   t   r   i   b   u   t   e   s   /
0000200   s   y   s   t   e   m   /   s   k   i   n   s   /   a   c   t
0000220   i   v   e   t   h   e   m   e  ht   4   0   4  ht   "   4   c
0000240   b   1   b   d   4   9   -   1   d   e   b   -   4   b   6   f
0000260   -   8   4   c   5   -   1   1   5   3   f   2   2   e   3   7
0000300   3   9   -   0   0   0   0   0   0   0   c   "  ht      "   1   .
0000320   4   c   b   1   b   d   4   9   -   1   d   e   b   -   4   b
0000340   6   f   -   8   4   c   5   -   1   1   5   3   f   2   2   e
0000360   3   7   3   9   -   0   0   0   0   0   0   0   c   ;   k   X
0000400   K   w   o   3   h   C   Q   t   R   L   G   m   j   E   0   Z
0000420   J   O   o   O   T   L   k   K   P   O   o   L   R   K   l   S
0000440   O   D   o   I   T   T   _   G   "  ht   -  ht   -  nl 

Awk


Awk is a pattern scanning and processing language, which is good for purposes of extracting or transforming text, such as producing formatted reports.  Read [4] for more details.

For well-formatted access.log in WLS, awk can be handy for extracting fields such as:
  • cs-method — The request method, for example GET or POST. This field has type <name>, as defined in the W3C specification.
  • cs-uri — The full requested URI. This field has type <uri>, as defined in the W3C specification.
  • sc-status — Status code of the response, for example (404) indicating a "File not found" status. This field has type <integer>, as defined in the W3C specification.

 bash-4.2$ awk '{ print $5, $6, $7 }' sample.log  | grep "\s404" | sort -r | uniq -c
      1 GET /xx-contentyyyyyyy/api/v1/instances/bootstrap/artifacts/namespaces/content:catalog/attributes/users/18446744073709551615 404
      1 GET /xx-contentyyyyyyy/api/v1/instances/bootstrap/artifacts/namespaces/content:catalog/attributes/system/skins/activetheme 404
      1 GET /xx-contentyyyyyyy/api/v1/instances/bootstrap/artifacts/namespaces/content:catalog/attributes/maintenancemode 404


Perl


Perl is a powerful programming language due to its unsurpassed regular expression and string parsing abilities.  In Perl, you can use patterns to locate the parts of strings that you want to change with its “search and replace” .

Search and replace is performed using s/regex/replacement/modifiers. The replacement is a Perl double-quoted string that replaces in the string whatever is matched with the regex . If there is a match, s/// returns the number of substitutions made; otherwise it returns false.


bash-4.2$ perl -n -p -e 's/^[^A-Z]*([A-Z]+)\s([^\"]*)\s(\".*)/$1 $2/g' sample.log | grep "\s404" | sort -r | uniq -c

      1 GET /xx-contentyyyyyyy/api/v1/instances/bootstrap/artifacts/namespaces/content:catalog/attributes/users/18446744073709551615    404
      1 GET /xx-contentyyyyyyy/api/v1/instances/bootstrap/artifacts/namespaces/content:catalog/attributes/system/skins/activetheme      404
      1 GET /xx-contentyyyyyyy/api/v1/instances/bootstrap/artifacts/namespaces/content:catalog/attributes/maintenancemode       404


Note that the above Perl example is not the optimal command for the designed purpose.  But, we just try to demonstrate as many Perl's features as possible in one example. 

In the above example, our substitution operator is:
s/^[^A-Z]*([A-Z]+)\s([^\"]*)\s(\".*)/$1 $2/g
or
regex: "^[^A-Z]*([A-Z]+)\s([^\"]*)\s(\".*)"
replacement: "$1 $2"
modifiers: "g"

where

  • regex
    • ^[^A-Z]* matches 2020-08-23      15:54:02        0.031   479     
    • The first capturing group ([A-Z]+) or $1 match GET     /xx-contentyyyyyyy/api/v1/instances/bootstrap/artifacts/namespaces/content:catalog/attributes/system/skins/activetheme
    • The second capturing group ([^\"]*) or $2 matches 404
    • Note that we have discarded the third capturing group or $3
    • \s matches a whitespace character (i.e., ht)
  • replacement
    • The whole line was changed to "$1 $2" or
      • GET     /xx-contentyyyyyyy/api/v1/instances/bootstrap/artifacts/namespaces/content:catalog/attributes/system/skins/activetheme 404
  • modifiers
    • The global modifier /g allows the matching operator to match within a string as many times as possible.  In our example, it is not needed.  But, for illustration only.

You can read this Perl script example to learn more of its features.

Acknowledgement


This author would like thank his co-worker Mohan Tadepalli for providing Perl examples and inspiring me to write this article.

References

Thursday, April 26, 2018

How to Debug "java.io.IOException: Connection reset by peer"?


There are many reasons that WebLogic server may throw below exception:
java.io.IOException: Connection reset by peer
In this article, we will use one specific case for discussion.

Stack Trace


####<Apr 26, 2018, 8:42:37,381 AM UTC> <Error> <HTTP> <myserver> <CloudConsoleServer_MyServices> <[ACTIVE] ExecuteThread: '23' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <XaUWE0Co100000000> <1524732157381> <[severity-value: 8] [rid: 0:1:2] [partition-id: 0] [partition-name: DOMAIN] > <BEA-101019> <[ServletContext@15863685[app:cp-myservices.ear module:mycloud path:null spec-version:3.1 version:_18.2.4.0.0_180422.1400]] Servlet failed with an IOException.
java.io.IOException: Connection reset by peer
        at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
        at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
        at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
        at sun.nio.ch.IOUtil.write(IOUtil.java:65)
        at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
        at weblogic.socket.NIOOutputStream$SingleBufferWrite.writeTo(NIOOutputStream.java:841)
        at weblogic.socket.NIOOutputStream$BlockingWriter.flush(NIOOutputStream.java:455)
        at weblogic.socket.NIOOutputStream$BlockingWriter.write(NIOOutputStream.java:334)
        at weblogic.socket.NIOOutputStream.write(NIOOutputStream.java:220)
        at weblogic.servlet.internal.ChunkOutput.writeChunkTransfer(ChunkOutput.java:625)
        at weblogic.servlet.internal.ChunkOutput.writeChunks(ChunkOutput.java:587)
        at weblogic.servlet.internal.ChunkOutput.flush(ChunkOutput.java:471)
        at weblogic.servlet.internal.ChunkOutput$3.checkForFlush(ChunkOutput.java:757)
        at weblogic.servlet.internal.ChunkOutput.write(ChunkOutput.java:373)
        at weblogic.servlet.internal.ChunkOutputWrapper.write(ChunkOutputWrapper.java:165)
        at weblogic.servlet.internal.ServletOutputStreamImpl.write(ServletOutputStreamImpl.java:186)
        at java.io.ByteArrayOutputStream.writeTo(ByteArrayOutputStream.java:167)
        at oracle.adfinternal.view.faces.caching.filter.ResponseOutputStream.writeContentTo(ResponseOutputStream.java:74)
        at oracle.adfinternal.view.faces.caching.filter.AdfFacesCachingResponse._flushContent(AdfFacesCachingResponse.java:147)
        at oracle.adfinternal.view.faces.caching.filter.AdfFacesCachingResponse.flush(AdfFacesCachingResponse.java:136)

How to Debug


In this case, our server is connected to many applications in other servers. So, the peer-in-suspect could be from either a browser or an application running in our infrastructure.

Given the stack trace, the first thing to check is find some clues from it.  For example, in this case, we saw:

 weblogic.servlet.internal.ServletOutputStreamImpl.write(ServletOutputStreamImpl.java:186)
 java.io.ByteArrayOutputStream.writeTo(ByteArrayOutputStream.java:167)
 oracle.adfinternal.view.faces.caching.filter.ResponseOutputStream.writeContentTo(ResponseOutputStream.java:74)
 oracle.adfinternal.view.faces.caching.filter.AdfFacesCachingResponse._flushContent(AdfFacesCachingResponse.java:147)
 oracle.adfinternal.view.faces.caching.filter.AdfFacesCachingResponse.flush(AdfFacesCachingResponse.java:136)


which means that WebLogic server is 
Writing the servlet response back to the client when the IOException was thrown

If this client were a browser, what happened could be:
The browser has shutdown the connection — either the browser crashed, or the browser shut the connection explicitly because the user closed that page or cancelled navigation on that page.

If this client were an application (i.e., a selenium or other testing tools), what happened could be:
Timeouts in those tools for how long they will wait for the response.
then
Maybe their logs would show you that they had closed the socket after some time.


HTTP Keep-Alive


In [1], the author surmized that it could be:
 " Very likely an issue with HTTP keepalive (persistent connections)."
However, this is not our case because:
Keep-alive is to make sure the socket stays open between requests. Our case is in the middle of a request, so there is no keepalive in use at that time. But conceptually it is sort of the same thing: if the client (i.e., browser) decides that the response isn't coming, it closes the socket.

If You Find Out Who's the Peer


Let assume the client is another Linux application, here are possible debugging steps:
The only thing to check at the system level is that if the machine was up the entire time — you can check its uptime, and look at dmesg for messages about the link going up or down. Otherwise, maybe the application logs will tell you if the process restarted/crashed, which is the more likely cause. 

Could tcpdump help in this case?  Probably not  because
There will probably be too much data from a tcpdump unless you know how to filter what you are looking for. 


References

  1. Possible Causes for "Connection reset by peer" when using NIOReferences

Monday, December 22, 2014

Java Security Manager: Troubshooting Security

In [1], we have discussed how to fix security violations when Java Security Manager is enabled at WebLogic Server start-up.  In this article, we will look at how to troubleshoot security policy-related issues by using the java.security.debug option.

java.security.debug


To troubleshoot security policy-related issues, you can configure Java Security Manager with the level of security-related information to be reported using:
java.security.debug  
To find out what the debug option offers, do:
java -Djava.security.debug=help
If using JDK 7, you can find more information from [2].  As for JDK 8, we have included the list of debugging options in the Addendum for your convenience.  Note that you need to separate multiple options with a comma.  For example, we will look at the output from the following combination of debug options:
-Djava.security.debug=policy,access


policy Option


Setting "policy" option will allow Security Manager to report the details of
Loading and granting permissions with policy file
For example, from the WebLogic Server log file, you can find the following entries:

policy: Adding policy entry: 
policy:   signedBy null
policy:   codeBase file:/home/myusername/wls1221141208/wlserver/server/lib/-
policy:   ("java.security.AllPermission" "" "")
policy:
policy: Adding policy entry: 
policy:   signedBy null
policy:   codeBase file:/home/myusername/wls1221141208/wlserver/modules/-
policy:   ("java.security.AllPermission" "" "")
policy:


which correspond to grant entries from the weblogic.policy:[5]

grant codeBase "file:/home/myusername/wls1221141208/wlserver/server/lib/-" {
  permission java.security.AllPermission;
};

grant codeBase "file:/home/myusername/wls1221141208/wlserver/modules/-" {
  permission java.security.AllPermission;
};

Beside of policy loading entries, you could also find other entries (e.g. permission granting entries) such as:

policy:   granting ("java.util.PropertyPermission" "java.version" "read")
policy:   granting ("java.util.PropertyPermission" "java.vendor" "read")


access Option


Enabling access option, allows Security Manager to print all results from the AccessController.checkPermission method.

You can use the following options with the access option:
  • stack: Include stack trace
  • domain: Dump all domains (i.e., protection domain) in context
  • failure:[3] Before throwing exception, dump stack and domain that do not have permission
You can also use the following options with the stack and domain options:
  • permission=<classname>[4]
    • Only dump output if specified permission is being checked 
  • codebase=<URL>
    • This option would be useful when customer desires to trace the permissions impact of only the code in a given code souce, such as jar file.
    • URL is the location of the specified code base. 
      • Note that because the comma (',") is used as multi options separator, if the URL contains comma, the security debugger would not work properly as expected, it is recommended that the URL should not include character comma (','), semicolon (';'), and  space.

Addendum


$ jdk-hs/bin/java -Djava.security.debug=help

all           turn on all debugging
access        print all checkPermission results
certpath      PKIX CertPathBuilder and
              CertPathValidator debugging
combiner      SubjectDomainCombiner debugging
gssloginconfig
              GSS LoginConfigImpl debugging
configfile    JAAS ConfigFile loading
configparser  JAAS ConfigFile parsing
jar           jar verification
logincontext  login context results
jca           JCA engine class debugging
policy        loading and granting
provider      security provider debugging
pkcs11        PKCS11 session manager debugging
pkcs11keystore
              PKCS11 KeyStore debugging
sunpkcs11     SunPKCS11 provider debugging
scl           permissions SecureClassLoader assigns
ts            timestamping

The following can be used with access:

stack         include stack trace
domain        dump all domains in context
failure       before throwing exception, dump stack
              and domain that didn't have permission

The following can be used with stack and domain:

permission=
              only dump output if specified permission
              is being checked
codebase=
              only dump output if specified codebase
              is being checked

The following can be used with provider:

engine=
              only dump output for the specified list
              of JCA engines. Supported values:
              Cipher, KeyAgreement, KeyGenerator,
              KeyPairGenerator, KeyStore, Mac,
              MessageDigest, SecureRandom, Signature.

References

  1. Java Security Manager: java.security.AccessControlException: access denied (Xml and More)
  2. Troubshooting Security
  3. Debugging Security Policy Issues
    • JAVA_OPTS="$JAVA_OPTS -Djava.security.debug=access:failure"
  4. Fine granularity diagnosis on security
    • -Djava.security.debug=access,stack,permission=java.io.FilePermission
  5. Java SecurityManager: "java.security" and "java.policy" Files (Xml and More)

Saturday, December 13, 2014

Java Security Manager: java.security.AccessControlException: access denied

The JVM has security mechanisms built into it that allow you to define restrictions to code through Java security policy files (i.e., java.policy file). The Java Security Manager[1] uses these policies to enforce a set of permissions granted to classes. The permissions allow specified classes running in that instance of the JVM to allow or not allow certain runtime operations.



In this article, we will cover how to resolve security violations such as
java.security.AccessControlException: access denied
when you start WebLogic Server with Java Security checking enabled (see [1] for how to enable Java Security Manager).

java.security.AccessControlException


AccessController is the main security enforcer in Java Security Manager.  It helps decide whether an access to a critical system resource is to be allowed or denied, based on the security policy currently in effect,  For example, an java.security.AccessControlException will be thrown when a permission was not granted to read weblogic.security.DumpContextHandler property as below:

Caused by: java.security.AccessControlException: access denied ("java.util.PropertyPermission" "weblogic.security.DumpContextHandler" "read")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:457)
at java.security.AccessController.checkPermission(AccessController.java:884)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1294)
at java.lang.System.getProperty(System.java:714)
at java.lang.Boolean.getBoolean(Boolean.java:254)
at weblogic.security.utils.SecurityUtils.(SecurityUtils.java:23)

If the security violations in your application are only a few, you may consider to add an entry like below in the default section of your policy file:

// default permissions granted to all protection domains
grant {
    ...
    permission java.util.PropertyPermission "weblogic.security.DumpContextHandler", "read";
    ...
};

"weblogic.policy" and "ojdbc.policy"


When you run applications in WebLogic server, Oracle has provided an OOTB policy file at:
${WL_HOME}/server/lib/weblogic.policy
If you specify it in the JVM option:
-Djava.security.policy=${WL_HOME}/server/lib/weblogic.policy
then the specified policy file will be loaded in addition to all the java policy files (see [1] for details). However,  OOTB weblogic.policy is not intended to cover all deployed applications.  For example, if you use Oracle JDBC Driver in your applications, you may need to add the grant entries specified in ojdbc.policy[2] onto the ones specified in weblogic.policy file.

Grant Entries


If you look at either weblogic.policy or ojdbc.policy file, there are many grant entries. The basic format of a grant entry is the following:[4]

  grant signedBy "signer_names", codeBase "URL",
        principal principal_class_name "principal_name",
        principal principal_class_name "principal_name",
        ... {
      permission permission_class_name "target_name", "action", 
          signedBy "signer_names";
      permission permission_class_name "target_name", "action", 
          signedBy "signer_names";
      ...
  };

Each grant entry includes one or more "permission entries" preceded by optional codeBase, signedBy, and principal name/value pairs that specify which code you want to grant the permissions.

Sometimes it will be too much to enumerate all permissions individually.  This is the time for granting permissions by any combination of the following entries:
  • SignedBy
  • Principal
  • CodeBase

Grant Permission by SignedBy


An example of granting permission(s) based on signer is shown below:[3]
keystore "kim.keystore";

// Here is the permission ExampleGame needs.
// It grants code signed by "terry" the
// HighScorePermission, if the
// HighScorePermission was signed by "chris"
grant SignedBy "terry" {
  permission
    com.scoredev.scores.HighScorePermission
      "ExampleGame", signedBy "chris";
};
A signedBy value indicates the alias for a certificate stored in the keystore. The public key within that certificate is used to verify the digital signature on the code; you grant the permission(s) to code signed by the private key corresponding to the public key in the keystore entry specified by the alias.

The signedBy value can be a comma-separated list of multiple aliases. An example is "Adam,Eve,Charles", which means "signed by Adam and Eve and Charles"; the relationship is AND, not OR. To be more exact, a statement like "Code signed by Adam" means "Code in a class file contained in a JAR which is signed using the private key corresponding to the public key certificate in the keystore whose entry is aliased by Adam".

Grant Permission by Principal


An example of granting permission(s) based on principal is shown below:
// Grant notification listener actions to standard roles

grant principal weblogic.security.principal.WLSGroupImpl "Administrators" {
    permission javax.management.MBeanPermission "*", "addNotificationListener";
    permission javax.management.MBeanPermission "*", "removeNotificationListener";

};
A principal value specifies a class_name/principal_name pair which must be present within the executing thread's principal set. The principal set is associated with the executing code by way of a Subject.

The principal_class_name may be set to the wildcard value, *, which allows it to match any Principal class. In addition, the principal_name may also be set to the wildcard value, *, allowing it to match any Principal name. When setting the principal_class_name or principal_name to *, do not surround the * with quotes. Also, if you specify a wildcard principal class, you must also specify a wildcard principal name.

Grant Permission by CodeBase


A codeBase value indicates the code source location; you grant the permission(s) to code from that location. An example of granting permission by CodeBase is shown below:
// Grant for internal applications when using WebLogic startup scripts
grant codeBase "file:${user.dir}/servers/${weblogic.Name}/tmp/_WL_internal/-" {
  permission java.security.AllPermission;
};

BNF Grammar


An informal BNF grammer for the Policy file format is given below, where non-capitalized terms are terminals:[12]

PolicyFile -> PolicyEntry | PolicyEntry; PolicyFile
PolicyEntry -> grant {PermissionEntry}; |
           grant SignerEntry {PermissionEntry} |
           grant CodebaseEntry {PermissionEntry} |
           grant PrincipalEntry {PermissionEntry} |
           grant SignerEntry, CodebaseEntry {PermissionEntry} |
           grant CodebaseEntry, SignerEntry {PermissionEntry} |
           grant SignerEntry, PrincipalEntry {PermissionEntry} |
           grant PrincipalEntry, SignerEntry {PermissionEntry} |
           grant CodebaseEntry, PrincipalEntry {PermissionEntry} |
           grant PrincipalEntry, CodebaseEntry {PermissionEntry} |
           grant SignerEntry, CodebaseEntry, PrincipalEntry {PermissionEntry} |
           grant CodebaseEntry, SignerEntry, PrincipalEntry {PermissionEntry} |
           grant SignerEntry, PrincipalEntry, CodebaseEntry {PermissionEntry} |
           grant CodebaseEntry, PrincipalEntry, SignerEntry {PermissionEntry} |
           grant PrincipalEntry, CodebaseEntry, SignerEntry {PermissionEntry} |
           grant PrincipalEntry, SignerEntry, CodebaseEntry {PermissionEntry} |
           keystore "url"
SignerEntry -> signedby (a comma-separated list of strings)
CodebaseEntry -> codebase (a string representation of a URL)
PrincipalEntry -> OnePrincipal | OnePrincipal, PrincipalEntry
OnePrincipal -> principal [ principal_class_name ] "principal_name" (a principal)
PermissionEntry -> OnePermission | OnePermission PermissionEntry
OnePermission -> permission permission_class_name
                 [ "target_name" ] [, "action_list"]
                 [, SignerEntry];

Some entries in the grammar are optional, If they are omitted, it signifies:

When Omitted
It Means
CodebaseEntry "any code base" (it doesn't matter where the code originates from)
SignerEntry "any signer" (it doesn't matter whether the code is signed or not or by whom)
PrincipalEntry "any principals"


The "target_name"is the name of the permission is aimed.  For java.io.FilePermission, the targets of this class can be specified as:

file
directory (same as directory/)
directory/file
directory/* (all files in this directory)
* (all files in the current directory)
directory/- (all files in the file system under this directory)
- (all files in the file system under the current directory)
"<<ALL FILES>>" (all files in the file system)

As an example, you may grant read permission to all files in the file system as below:
permission java.io.FilePermission "<<ALL FILES>>", "read"; 

Finally, a set of actions can be specified together as a comma-separated composite string as below:
permission java.io.FilePermission "WEBLOGIC-APPLICATION-ROOT${/}-", "read, write, delete, execute";

References

Thursday, October 9, 2014

New JDK 8 support in WebLogic Server 12.1.3.0

Oracle has just announced that Oracle WebLogic Server 12.1.3 has been certified on Java SE 8. It is supported on:

  • Windows
  • Linux
  • Solaris 64-bit 

platforms with HotSpot JDK8 Update 20 or later.

If you want to learn more about what is supported and what are the limitations, check:

Thursday, November 7, 2013

Java Throwable: ClassNotFoundException vs. NoClassDefFoundError

Many times we have confused ourselves with the following two Java Throwable messages:

Although both of them are related to Java Classpath,[7] they are different.[1] In a nutshell, they differ in this way:
  • ClassNotFoundException
    • Thrown when an application tries to load a class at run-time and name was provided during runtime not at compile time
  • NoClassDefFoundError[11,12]
    • When JVM or a ClassLoader instance is not able to find a particular class at runtime which was available during compile time

ClassNotFoundException


ClassNotFoundException is thrown when an application tries to load in a class through its string name using:
  • The forName method in class Class.
  • The findSystemClass method in class ClassLoader .
  • The loadClass method in class ClassLoader.
but no definition for the class with the specified name could be found. See How-To section below for solutions.

NoClassDefFoundError


The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found. One way to debug NoClassDefFoundError is going back to the design-time environment. Using an IDE, you might be able to find where the class is coming from at compile time. Then use that as a clue to find why that class cannot be found at runtime. See How-To section for more details.

What Could Go Wrong?


Classpath[7] in Java is path to directory or list of directory which is used by ClassLoaders[3] to find and load class in Java program. If a class cannot be found at runtime, it may be due to:
  • Classloaders are not set up correctly[3]
  • Class is corrupted
    • Java compiler is not backwards compatible. For example, bytecode generated with JDK 7 won't run in Java 1.6 JVM.[2]
  • Jar file could be renamed in the runtime environment
  • Your startup script may have overridden Classpath environment variable
  • You might be running your program using jar command and class was not defined in manifest file's ClassPath attribute.

How to Resolve it?


The application that triggered the request to load a class receives a ClassNotFoundException or NoClassDefFoundError if neither the classloader nor any of its ancestors can locate the class.[3] In that case, you can take the following actions:
  • You can use System.getproperty("java.class.path") to get the class path used by your Java application at runtime.[4]
  • Try to run with -classpath option using the classpath you think would work: if it works, then it's a sign that some one is overriding java classpath.
  • Check the permission of your jar files.  Your application may not be able to access them.
  • Enable class loading traces at JVM level. For example, you can specify -verbose:class for both JRockit and HotSpot.[5]
  • If your application is deployed in WebLogic server, read [3] and enable classloader debugging. 
    •  For example, you may want to set:
      • -Dweblogic.utils.classloaders.GenericClassLoader.Verbose=true 
      • -Dweblogic.utils.classloaders.ChangeAwareClassLoader.Verbose=true
    • You can also use Classloader Analysis Tool (http://localhost:port/wls-cat/) which is deployed by default on admin servers of domains in development mode.[6]
    • If your application runs in one environment and not in another,
      • Try adding the CLASSPATH explicitly pointing to your jars in setDomainEnv script 
      • You can also set "EXT_PRE_CLASSPATH=...." or "EXT_POST_CLASSPATH=..." where "..." are your jar files. The setDomainEnv.sh will pick up these and add to CLASSPATH. The above environment variables can be set when you log on or somewhere at the top of setDomainEnv.sh.



References

  1. 3 ways to solve java.lang.NoClassDefFoundError in Java J2EE
  2. Is JDK “upward” or “backward” compatible?
  3. WebLogic's Classloading Framework (Xml and More)
  4. System Properties
  5. -verbose:class Option
  6. Using the new WebLogic Classloader Analysis Tool (CAT)
    • Note that I'm not sure if this is still available in newer WLS releases.
  7. How to Set Classpath for Java on Windows Unix and Linux
    • Main difference between PATH and CLASSPATH is that former is used to locate Java commands while later is used to locate Java class files.
  8. java.lang.UnsatisfiedLinkError: Setting Environment Variable (Xml and More)
  9. Using the Classloader Analysis Tool (CAT)
  10. WebLogic Server (WLS) Support Pattern: Investigating Different Classloading Issues (Doc ID 1572862.1)
  11. If you use JPA 2.1 with WLS 12.1.1 or 12.1.2, then you may see this (because JPA 2.1 only supported starting in 12.1.3):
    • java.lang.NoClassDefFoundError: javax/persistence/StoredProcedureQuery
  12. java.lang.NoClassDefFoundError: sun/io/CharacterEncoding (Xml and More)


Tuesday, November 5, 2013

WebLogic Server Cluster Messaging Protocols—Unicast vs. Multicast

WebLogic Server clusters form a loosely-federated group of managed servers that provide a model for applications to leverage for achieving scalability, load balancing, and failover.[1]

To support the above-said functionality, the cluster uses a messaging model for members of the cluster to exchange the information required to keep the cluster in sync.  WebLogic Server supports two cluster messaging protocols:[1,2]
  • Multicast – This protocol, which relies on UDP Multicast, has been around since WebLogic Server introduced clustering back in WebLogic Server version 4.0.
  • Unicast – This protocol, which relies on point-to-point TCP/IP sockets, was added in WebLogic Server 10.0.
In this article, we will look at an example cluster (i.e, CustomerCluster) which is composed of two cluster members:
  • CustomerServer_1
  • CustomerServer_2
Note that, in our configuration, we have both servers installed on the same machine.  But, the best practice is to install them on different machines in case that one of them crashes.

CustomerCluster


CustomerCluster mentioned here is configured in the CRM Domain of CRM Fusion Application.  There are two members in the cluster.  To sync up each other, unicast cluster messaging mode was chosen as shown below:

It is important to note that although unicast is the default protocol, Oracle fully supports both protocols equally. As stated in [1], parts of the WLS documentation suggest or imply that multicast is only supported for backwards compatibility (see [4]). This suggestion or implication is incorrect.  For example, if you are using WebLogic Server 12c, the choice of protocols should not be influenced by this wording in the WLS documentation. Read [1] for a good comparison for clusters using either unicast or multicast protocols.

Group Leader Strategy


Unicast protocol relies on point-to-point TCP/IP sockets.  So, WebLogic Server’s unicast implementation uses a group leader strategy to limit the growth in the number of sockets required as the cluster size grows.  The cluster is split into one or more groups; each group has a group leader.  Group members communicate with the group leader; group leaders also communicate with other group leaders in the cluster. If a group leader dies, the group elects another group leader.  In the example CustomerCluster, CustomerServer_1 is the group leader (see Figure).


Final Words


When configuring WebLogic Server clusters for unicast communications, if the servers are running on different machines, you must explicitly specify their listen addresses or DNS names.

To find out more information, read the following articles:

References

  1. WebLogic Server Cluster Messaging Protocols
  2. WebLogic Server
    Version: 10.3.6.0 is used in the demonstration of this article.
  3. Interview Question - How to persist session across Weblogic?
  4. Communications In a Cluster

Monday, November 4, 2013

Java EE and GlassFish Server Roadmap Update

On 11/04/2013, Oracle has just announced a roadmap update on Java EE and GlassFish.  The major changes include, but not limited to:
  • Oracle will no longer release future major releases of Oracle GlassFish Server with commercial support – specifically Oracle GlassFish Server 4.x with commercial Java EE 7 support will not be released.
  • Commercial Java EE 7 support will be provided from WebLogic Server.
  • Oracle GlassFish Server will not be releasing a 4.x commercial version

Thursday, September 26, 2013

WebLogic Startup Slowness Caused by Kernel's Random Number Generator

Java Application (i.e., WebLogic Server) could be slow at startup time and it could be caused by the slowness of random number generator used by the application.  You can read [2] for the case that discusses the slowness of WebLogic startup.

In this article, we will examine the following issues:
  • /dev/random vs. /dev/urandom
    • How to test the performance of a random number generator?
    • How to configure it?
  • Security considerations
on Linux systems.  Note that this can happen with WLS running on AIX too.

/dev/random vs. /dev/urandom


Without much ado, here is the man output for "urandom":
The character special files /dev/random and /dev/urandom (present since Linux 1.3.30) provide an interface to the kernel's random number generator.  File /dev/random has major device number 1 and minor device number 8.  File /dev/urandom has major device number 1  and  minor  device number 9.
The  random  number  generator  gathers environmental noise from device drivers and other sources into an entropy  pool.   The  generator  also keeps  an  estimate of the number of bits of noise in the entropy pool.  From this entropy pool random numbers are created. 
When read, the /dev/random device will only return random bytes  within the estimated number of bits of noise in the entropy pool.  /dev/random should be suitable for uses that need very high quality randomness such as  one-time  pad  or  key generation.  When the entropy pool is empty, reads from /dev/random will block until additional environmental  noise is gathered. 
A  read  from  the  /dev/urandom device will not block waiting for more entropy.  As a result, if  there  is  not  sufficient  entropy  in  the entropy  pool,  the  returned  values are theoretically vulnerable to a cryptographic attack on the algorithms used by the  driver.   Knowledge of how to do this is not available in the current non-classified literature, but it is theoretically possible that such an attack may  exist.  If this is a concern in your application, use /dev/random instead.

How to Test?


You can use "time" command to measure the performance of each random number generator.  For example, here is the output from the Linux system.

$time head -1 /dev/random                                                  
real    0m9.718s
user    0m0.000s
sys     0m0.001s


$ time head -1 /dev/./urandom
real    0m0.002s
user    0m0.000s
sys     0m0.002s

As you can see that "/dev/urandom" is much faster because it's non-blocking.  However, /dev/random will block until additional environmental noise is gathered and takes longer time to return.

How to Configure?


You can configure which source of seed data for SecureRandom to use at JVM level or at WLS' command-line level.

At the JVM level, you can change the value of securerandom.source property in the file:
  • $JAVA_HOME/jre/lib/security/java.security
Here is the description of securerandom.source property:

# Select the source of seed data for SecureRandom. By default an
# attempt is made to use the entropy gathering device specified by
# the securerandom.source property. If an exception occurs when
# accessing the URL then the traditional system/thread activity
# algorithm is used.
#
# On Solaris and Linux systems, if file:/dev/urandom is specified and it
# exists, a special SecureRandom implementation is activated by default.
# This "NativePRNG" reads random bytes directly from /dev/urandom.
#
# On Windows systems, the URLs file:/dev/random and file:/dev/urandom
# enables use of the Microsoft CryptoAPI seed functionality.
#
securerandom.source=file:/dev/urandom

Or, you can specify which source of seed data to use by adding
  • -Djava.security.egd=file:/dev/./urandom
to the java command-line that starts WebLogic Server.

Security Considerations


In [1], it warns that if you choose /dev/urandom over /dev/random for better performance, you should be aware of that:
This workaround should not be used in production environments because it uses pseudo-random numbers instead of genuine random numbers.


References

  1. Random Number Generator May Be Slow on Machines With Inadequate Entropy
  2. Weblogic starts slow
  3. Fusion Middleware Performance and Tuning for Oracle WebLogic Server
  4. Oracle® Fusion Middleware Tuning Performance of Oracle WebLogic Server 12c (12.2.1)
  5. Fusion Middleware Tuning Performance of Oracle WebLogic Server (12.2.1.3.0)

Wednesday, August 28, 2013

Auto-Correlating Session IDs in Oracle Application Test Suite (OATS)

Similar to HP LoadRunner, Oracle Application Test Suite (OATS)[1] is an automated performance and test automation product from Oracle for monitoring system behavior and application performance. It's especially useful for Oracle Fusion Application's performance evaluation.

Oracle Open Script (or Oracle Functional Testing) is one of the components in OATS, which is integrated with Oracle Load Testing and Oracle Test Manager. It is also a load testing script generator, which is integrated with Eclipse to support script development and debugging. In the current offering, it only runs on Windows.

Correlation


Correlation of dynamic session values is a major task for load test scripting[2]. When a server in AUT (application under test) exchanges dynamic session values with the browser. OpenScript can auto-correlate dynamic session values—For example session IDs.

What's Session ID?


Session ID is used in session tracking.  Session tracking enables you to track a user's progress over multiple servlets or HTML pages, which, by nature, are stateless. A session is defined as a series of related browser requests that come from the same client during a certain time period. Session tracking ties together a series of browser requests—think of these requests as pages—that may have some meaning as a whole, such as a shopping cart application.

Session ID is a piece of data that is exchanged between the application's web server and the user agent (or browser). It is typically used to identify a specific user logged on to the application for a particular duration of his/her visit (or session).

Session ID is given per Session. It is often destroyed when the user logs off from the application. Next time you visit the same site, you will have a different session ID. The correlation task is to identify these dynamic values and substitute variables for them in the load testing scripts.

As you know, Oracle Fusion Applications maintain a rich set of dynamic session values. Correlation done manually requires in-depth knowledge of the application itself and can also be error prone. Fortunately, most correlations needed for successful playbacks can be done automatically by Oracle Open Script. For example, it auto-correlates Session IDs.

Different Ways of Storing Session IDs


There are multiple ways for a web page to pass session ID to a web server. Session ID can be stored in:
  • Cookie[6]
  • URL
  • HTML page

Storing Session ID in Cookies


Cookie is the text information that application places in the client's hard disk. Browser sends the cookie back to the application to keep the state. On WebLogic Server, use of session cookies is enabled by default and is recommended, but you can disable them by setting cookies-enabled property[3] to false.
If cookie is enabled on the browser, you often find the following entry in the HTTP headers:
  • JSESSIONID=HDe6IhnMFZFtKrVsNi0eUsZ0NWaaIaw_OT2vW7CDpZ8sfz9v4Hqf!-777642468!-553692576;
Note that JSESSIONID is the default session tracking cookie name used by WLS. You can configure WebLogic Server session tracking by defining properties in the WebLogic-specific deployment descriptor,weblogic.xml. For a complete list of session attributes, see session-descriptor[3].

Storing Session ID in URL


Session ID can be sent back to the server as a string appended to URL following a question mark (i.e., "?")
On WLS, you can enable URL rewriting by setting url-rewriting-enabled property, which encodes the session ID into the URL and provides session tracking if cookies are disabled in the browser. However, storing Session ID in URLs is less secure than storing it in cookies[5].

Storing Session ID in HTML Page


Finally, session ID can also be stored in the hidden field of a HTML page and submitted by the Post Command:

  • <input type="hidden" name="sessionID" value="54321abcd">

Most user agents (or browsers) allow you to store information in a HiddenField control, which renders as a standard HTML hidden field. A hidden field does not render visibly in the browser, but you can set its properties just as you can with a standard control. When a page is submitted to the server, the content of a hidden field is sent in the HTTP form collection along with the values of other controls. A hidden field acts as a repository for any page-specific information (including Session ID) that you want to store directly in the page.

References

  1. Oracle Application Testing Suite
  2. OpenScript for Load Testing Script Troubleshooting (Tutorial)
  3. weblogic.xml Deployment Descriptor Elements
  4. Extended Session ID format in WebLogic Server (12.1.1)
    • A server startup flag, -Dweblogic.servlet.useExtendedSessionFormat=true, retains the information that the load-balancing application needs for session stickiness. 
    • The extended session ID format will be part of the URL if URL rewriting is activated, and the startup flag is set to true.
  5. Why is passing the session id as url parameter insecure?
  6. OAM 11g Single Sign-On and OAM 11g Cookies
    • Note that the cookie model is different between 10g and 11g.
  7. OATS: Tie All Processes Together — from OpenScript to Scenario (Xml and More)

Monday, August 12, 2013

How to Investigate: Failed to Bind to Port on Linux

From the server log file (i.e., CRMCommonServer_1.log) of WebLogic, I have found the following messages:

####<Aug 12, 2013 10:40:43 AM PDT> <Emergency> <Security> <myserver> <CRMCommonServer_1> <[STANDBY] ExecuteThread: '4' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1376329243268> <BEA-090087> <Server failed to bind to the configured Admin port. The port may already be used by another process.>
####<Aug 12, 2013 10:40:43 AM PDT> <Error> <Server> <myserver> <CRMCommonServer_1> <DynamicListenThread[Default]> <<WLS Kernel>> <> <> <1376329243268> <BEA-002606> <Unable to create a server socket for listening on channel "Default". The address 10.241.88.31 might be incorrect or another process is using port 9004: java.net.BindException: Address already in use.>

In this article, I will show you how to investigate: 
  • Which process is using port 9004?

Netstat Command on Linux


To investigate failed-to-bind-to -port issue, netstat comes in handy on Linux systems.  netstat command can be used to:
  • Print network connections, routing tables, interface statistics, masquerade connections, and multicast memberships

In this detective work, we have used the following options:

   -a, --all
       Show both listening and non-listening sockets.  With the --interfaces  option,  show  inter-
       faces that are not marked
   -p, --program
       Show the PID and name of the program to which each socket belongs.

The results are shown below:

$ netstat -ap | grep 9004 (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 myserver.us.ora:interserver myserver.oracle.com:9004 ESTABLISHED 12550/oidldapd tcp 0 0 myserver.us.oracle.com:9004 myserver.ora:interserver ESTABLISHED 22328/java


From the output, we know a Java application (i.e., process 22328) is using port 9004. When the first socket is bound to that port, then no other socket could be bound on port 9004 as long as the first socket remains open.  To know which application it is, we check out that process' command line:
  • $ vi /proc/22328/cmdline 
On the command line, we have found the following information:
  • -Dweblogic.Name=AdminServer
Also, BIDomain was mentioned there. So, that process is the AdminServer of BIDomain.

Port 7020


Similarly, we have seen port 7020 was used in another server's log file:
  • <BEA-002606> <Unable to create a server socket for listening on channel "Default". The address 10.241.88.31 might be incorrect or another process is using port 7020: java.net.BindException: Address already in use.>
When you tried:
    # netstat -ap  |grep 7020

    No entries have been returned.   However, if you use:

    # netstat -an  |grep 7020

    You could find one entry:

    tcp        0      0 ::ffff:10.241.88.31:7020    :::*                        LISTEN

    In this case, we need to use the following command line:

    # netstat -ap --numeric-ports |grep 7020
    tcp        0      0 slcag044.us.oracle.com:7020 *:*                         LISTEN      21696/java      

    So, we know process 21696 is using port 7020.  To investigate further, we typed:
    # netstat -ap  |grep  21696
    tcp        0      0 slcag044.us.oracle.:dpserve *:*                         LISTEN      21696/java

    It shows dpserve in the place of 7020.  So, that's why our first search ended up with no entries. Now we know port 7020 was used by the dpserve protocol for service type dpserve[2,3].

    Our Solution


    In our case, we need to re-order our start-up steps (see [4] for another approach). Instead of starting BIDomain first, we need to start it last. To fix our issue, we have done:
    • Shut down BIDomain 
    • Start up CRMDomain 
    • Start up BIDomain

    References

    Friday, August 2, 2013

    Linux: "File size limit exceeded" or "Too many open files in system"

    When running my benchmark, I have run into the following exception:
    • java.io.FileNotFoundException

    Too many open files in system


    The above exception is caused by:
    • Too many open files in system
    as found in the MyServer_1-diagnostic.log

    [2013-06-27T15:40:03.611-07:00] [CRMCommonServer_1] [ERROR] [] [oracle.security.audit.ajl.loader.AuditLoaderManager] [tid: AuditLoaderRunner] [ecid: 0000Jy7mm0L7y0I_IpG7yf1Hn9FC0001na,0] IAU:IAU-5046: Stopping AuditLoader, caught exception: oracle.security.audit.AuditException: java.io.FileNotFoundException: /slot/.../MyDomain/servers/myserver_1/logs/iau/state/auditloader.state (Too many open files in system)[[
            at oracle.security.audit.service.AuditLoaderManager.readMessages(AuditLoaderManager.java:276)
            at oracle.security.audit.service.AuditLoaderManager$Runner.run(AuditLoaderManager.java:335)
    Caused by: java.io.FileNotFoundException: /slot/.../MyDomain/servers/MyServer_1/logs/iau/state/auditloader.state (Too many open files in system)
            at java.io.FileOutputStream.open(Native Method)
            at java.io.FileOutputStream.(FileOutputStream.java:194)
            at java.io.FileOutputStream.(FileOutputStream.java:145)
            at java.io.FileWriter.(FileWriter.java:73)
            at oracle.security.audit.ajl.loader.AuditLoader.saveState(AuditLoader.java:213)
            at oracle.security.audit.service.AuditLoaderManager.readMessages(AuditLoaderManager.java:262)
            ... 1 more

    User Level File Descriptor Limits



    To view current open file limit for the current Linux user, run command:

    $ulimit -n
    8192

    To set it to a new value for this running session, which takes effect immediately, run command:

    $ ulimit -n 16384


    Alternatively, if you want the changes to survive reboot, do the following:
    1. Exit all shell sessions for the user you want to change limits on.
    2. As root, edit the file /etc/security/limits.conf and add these two lines toward the end:
      • user1 soft nofile 16384
        user1 hard nofile 16384
    The two lines above changes the max number of file handles - nofile - to new settings.
    • Save the file.
    • Login as the user1 again. The new changes will be in effect.

    System-wide File Descriptors Limits


    On Linux, there is also a system-wide configuration parameter named:
    • fs.file_max
    Use the following command to display maximum number of open file descriptors allowed on the system:

    $cat /proc/sys/fs/file-max
    100000

    Many application such as Oracle database or WebLogic server needs this setting quite higher. So you can increase the maximum number of open files by setting a new value in kernel variable /proc/sys/fs/file-max as follows (login as the root):

    # sysctl -w fs.file-max=262144

    Above command forces the limit to 262144 files. You need to edit /etc/sysctl.conf file and put following line so that after reboot the setting will remain as it is:

    # vi /etc/sysctl.conf

    Append a configuration directive as follows:

    fs.file-max = 262144

    Save and close the file. Users need to log out and log back in again to changes take effect or just type the following command:

    # sysctl -p

    Verify your settings with command:

    # cat /proc/sys/fs/file-max

    OR

    # sysctl fs.file-max

    Final Words


    Note that commands used in this article are good for the following Linux release:

    $ cat /etc/*-release
    Enterprise Linux Enterprise Linux Server release 5.8 (Carthage)
    Oracle Linux Server release 5.8
    Red Hat Enterprise Linux Server release 5.8 (Tikanga)


    References

    1. Need to “calculate” optimum ulimit and fs.file-max values according to my own server needs
    2. Verifying Kernel Parameters
    3. Linux Increase The Maximum Number Of Open Files / File Descriptors (FD)

    © Travel for Life Guide. All Rights Reserved.

    Analytical Insights on Health, Culture, and Security.