good article--
http://seekda.com/blog/write-your-first-web-services-client-%E2%80%93-part-1-finding-and-testing-services/
Wednesday, September 24, 2008
REST web services
Representational State Transfer (popularly known as REST) is a popular architectural
style of building web services. It doesn’t depend on a SOAP envelope, but it
does leverage XML and the HTTP protocol. Statistics revealed by large web-based
companies like Amazon and Yahoo! shows that a majority of their consumers use a
REST interface.
Unfortunately, Java EE 5 doesn’t require support for REST web services and each
vendor supports its own approach. GlassFish supports RESTful web services by creating
an implementation of the javax.ws.Provider interface. Vendors such as
Oracle allow you to convert a Java object into a web service by using proprietary configuration
or a proprietary annotation. Check your vendor’s documentation to see if
they provide REST support, and see how that support is implemented. For more
information on REST, hop over to http://en.wikipedia.org/wiki/Representational_
State_Transfer.
style of building web services. It doesn’t depend on a SOAP envelope, but it
does leverage XML and the HTTP protocol. Statistics revealed by large web-based
companies like Amazon and Yahoo! shows that a majority of their consumers use a
REST interface.
Unfortunately, Java EE 5 doesn’t require support for REST web services and each
vendor supports its own approach. GlassFish supports RESTful web services by creating
an implementation of the javax.ws.Provider interface. Vendors such as
Oracle allow you to convert a Java object into a web service by using proprietary configuration
or a proprietary annotation. Check your vendor’s documentation to see if
they provide REST support, and see how that support is implemented. For more
information on REST, hop over to http://en.wikipedia.org/wiki/Representational_
State_Transfer.
Monday, September 22, 2008
Business Process Execution Language
BPEL (Business Process Execution Language) is one of the new buzzwords thrown around with the same frequency as SOA (Service Oriented Architecture). Let us make an attempt to dismantle this jargon and try and understand the context and usage of this term.
BPEL talks about business processes. Hence, we first need to take a look at this term. It actually means what we think about this term. It is some work that we need to carry out (e.g. transfer money between two accounts, or purchase goods, or generate invoice). Usually, it is composed of a sequence of steps or actions in a specific order. When all the steps are completed successfully, the business process is considered to be complete and successful as as whole. A business process is rarely all-automated, and is usually a mixture of automated steps plus human interventions. Also, it can involve interactions with various other applications/systems inside the organization, or even outside. Hence, usually some sort of integration-related requirements are a part of any business process.
Now, what if we can describe a business processes in a language of its own? Better yet, what if we can implement it as a service (usually a Web service)? That is where we start moving from a business process to BPEL. If we can create a service that spans across all the steps necessary to complete the objectives of the business process, we would provide the technology support for implementing this as well. Hence, we can consider BPEL as a language that allows us to combine multiple small services (called as fine-grained services in the jargon) to create a big service that implements our business process (called as coarse-grained service in the jargon), in the right sequence.
BPEL, like anything else, these days, is based on XML. It is a part of the Web Services specifications. It allows us to define, carry out (i.e. orchestrate in the jargon), and manage business processes. The business processes themselves, as mentioned earlier, are implemented as Web services in the most common form. Therefore, we can crudely define BPEL also as a language that arranges one Web service after the other in a well-defined sequence, and gets some useful work done out from it (which we call as a business process).
The whole idea here is that non-technical people should be able to create and describe business processes. For taking the idea further, most BPEL development environments provide intuitive IDEs that are almost completely GUI-driven. This means that business analysts can not only elicit and describe requirements in plain English, but then can actually draw the flow of events as it is supposed to happen (e.g. Receive account numbers and amount -> Validate accounts -> Perform funds transfer -> On success, return ‘Success’ message, but on failure, return ‘Error’ message) using ready-made icons. Then how is this different from the use cases and sequence diagrams in UML? Well, the idea is quite similar in concept. However, the difference is that BPEL is closely tied to the SOA/Web services buzz (instead of the object orientation buzz), and secondly BPEL diagrams generate code in XML-like syntax (unlike the Java/C++ syntax as in the case of UML).
BPEL talks about business processes. Hence, we first need to take a look at this term. It actually means what we think about this term. It is some work that we need to carry out (e.g. transfer money between two accounts, or purchase goods, or generate invoice). Usually, it is composed of a sequence of steps or actions in a specific order. When all the steps are completed successfully, the business process is considered to be complete and successful as as whole. A business process is rarely all-automated, and is usually a mixture of automated steps plus human interventions. Also, it can involve interactions with various other applications/systems inside the organization, or even outside. Hence, usually some sort of integration-related requirements are a part of any business process.
Now, what if we can describe a business processes in a language of its own? Better yet, what if we can implement it as a service (usually a Web service)? That is where we start moving from a business process to BPEL. If we can create a service that spans across all the steps necessary to complete the objectives of the business process, we would provide the technology support for implementing this as well. Hence, we can consider BPEL as a language that allows us to combine multiple small services (called as fine-grained services in the jargon) to create a big service that implements our business process (called as coarse-grained service in the jargon), in the right sequence.
BPEL, like anything else, these days, is based on XML. It is a part of the Web Services specifications. It allows us to define, carry out (i.e. orchestrate in the jargon), and manage business processes. The business processes themselves, as mentioned earlier, are implemented as Web services in the most common form. Therefore, we can crudely define BPEL also as a language that arranges one Web service after the other in a well-defined sequence, and gets some useful work done out from it (which we call as a business process).
The whole idea here is that non-technical people should be able to create and describe business processes. For taking the idea further, most BPEL development environments provide intuitive IDEs that are almost completely GUI-driven. This means that business analysts can not only elicit and describe requirements in plain English, but then can actually draw the flow of events as it is supposed to happen (e.g. Receive account numbers and amount -> Validate accounts -> Perform funds transfer -> On success, return ‘Success’ message, but on failure, return ‘Error’ message) using ready-made icons. Then how is this different from the use cases and sequence diagrams in UML? Well, the idea is quite similar in concept. However, the difference is that BPEL is closely tied to the SOA/Web services buzz (instead of the object orientation buzz), and secondly BPEL diagrams generate code in XML-like syntax (unlike the Java/C++ syntax as in the case of UML).
Thursday, September 18, 2008
All about JAAS
All about JAAS
Have you ever needed to create a login authentication mechanism for an application? Odds are, you have, and probably more than once, with each new implementation being close, but not identical, to the previous one. For example, one implementation might use an Oracle database, another might use an NT authentication, and another, an LDAP (lightweight access directory protocol) directory. Wouldn't it be nice to support all these security mechanisms without changing any application-level code?
Now in the Java world, you can with the Java Authentication and Authorization Service (JAAS). This relatively new API was an extension in J2SE (Java 2 Platform, Standard Edition) 1.3, is a core API in J2SE 1.4, and is also part of the J2EE (Java 2 Platform, Enterprise Edition) 1.3 specification.
Have you ever needed to create a login authentication mechanism for an application? Odds are, you have, and probably more than once, with each new implementation being close, but not identical, to the previous one. For example, one implementation might use an Oracle database, another might use an NT authentication, and another, an LDAP (lightweight access directory protocol) directory. Wouldn't it be nice to support all these security mechanisms without changing any application-level code?
Now in the Java world, you can with the Java Authentication and Authorization Service (JAAS). This relatively new API was an extension in J2SE (Java 2 Platform, Standard Edition) 1.3, is a core API in J2SE 1.4, and is also part of the J2EE (Java 2 Platform, Enterprise Edition) 1.3 specification.
Developing secure web applications
BASIC CONCEPTS
1. Authentication: Authentication is the process of identifying a person or even a system, such as an application and validating their credentials.
2. Authorization: Authorization is the process of determining whether a user is permitted to access a particular resource that she has requested.
3. Data integrity: Data integrity is the process of ensuring that the data is not tampered with while in transit from the sender to the receiver.
4. Confidentiality or data privacy: Confidentiality is the process of ensuring that no one except the intended user is able to access sensitive information. The difference between authorization and confidentiality is in the way the information is protected. Authorization prevents the information from reaching unintended parties in the first place, while confidentiality ensures that even if the information falls into the wrong hands, it remains unusable
5. Auditing: Auditing is the process of recording security-related events taking place in the system in order to be able to hold users accountable for their actions.
6. Malicious code: A piece of code that is meant to cause harm to computer systems is called malicious code. This includes viruses, worms, and Trojan horses.
7. Web site attacks: A web site may be attacked by different people for different reasons. For example, a hacker may attack for pleasure, a terminated employee may attack for revenge, or a professional thief may attack for the purpose of stealing credit card numbers.
Broadly, there are three types of web site attacks:
• Secrecy attacks—Attempts to steal confidential information by sniffing the communications between two machines. Encrypting the data being transmitted can prevent such attacks.
• Integrity attacks—Attempts to alter information in transit with malicious intent. If these attempts succeed, it will compromise the data integrity. IP spoofing is one of the common techniques used in integrity attacks. In this technique, the intruder sends messages to a server with an IP address indicating that the message is coming from a trusted machine. The server is thus fooled into giving access to the intruder. Such attacks can be prevented by using strong authentication techniques, such as public-key cryptography.
• Denial-of-service attacks (or availability attacks)—Attempts to flood a system with fake requests so that the system remains unavailable for legitimate requests. Creating network congestion by sending spurious data packets also comes under this category. Such attacks can be prevented by using firewalls that block network traffic on unintended ports.
1. Authentication: Authentication is the process of identifying a person or even a system, such as an application and validating their credentials.
2. Authorization: Authorization is the process of determining whether a user is permitted to access a particular resource that she has requested.
3. Data integrity: Data integrity is the process of ensuring that the data is not tampered with while in transit from the sender to the receiver.
4. Confidentiality or data privacy: Confidentiality is the process of ensuring that no one except the intended user is able to access sensitive information. The difference between authorization and confidentiality is in the way the information is protected. Authorization prevents the information from reaching unintended parties in the first place, while confidentiality ensures that even if the information falls into the wrong hands, it remains unusable
5. Auditing: Auditing is the process of recording security-related events taking place in the system in order to be able to hold users accountable for their actions.
6. Malicious code: A piece of code that is meant to cause harm to computer systems is called malicious code. This includes viruses, worms, and Trojan horses.
7. Web site attacks: A web site may be attacked by different people for different reasons. For example, a hacker may attack for pleasure, a terminated employee may attack for revenge, or a professional thief may attack for the purpose of stealing credit card numbers.
Broadly, there are three types of web site attacks:
• Secrecy attacks—Attempts to steal confidential information by sniffing the communications between two machines. Encrypting the data being transmitted can prevent such attacks.
• Integrity attacks—Attempts to alter information in transit with malicious intent. If these attempts succeed, it will compromise the data integrity. IP spoofing is one of the common techniques used in integrity attacks. In this technique, the intruder sends messages to a server with an IP address indicating that the message is coming from a trusted machine. The server is thus fooled into giving access to the intruder. Such attacks can be prevented by using strong authentication techniques, such as public-key cryptography.
• Denial-of-service attacks (or availability attacks)—Attempts to flood a system with fake requests so that the system remains unavailable for legitimate requests. Creating network congestion by sending spurious data packets also comes under this category. Such attacks can be prevented by using firewalls that block network traffic on unintended ports.
Wednesday, September 17, 2008
What is String literal pool and use of String.intern method?
How to create a String
There are two ways to create a String object in Java:
Using the new operator. For example,
String str = new String("Hello");.
Using a string literal or constant expression). For example,
String str="Hello"; (string literal) or
String str="Hel" + "lo"; (string constant expression).
What is difference between these String's creations? In Java, the equals method can be considered to perform a deep comparison of the value of an object, whereas the == operator performs a shallow comparison. The equals method compares the content of two objects rather than two objects' references. The == operator with reference types (i.e., Objects) evaluates as true if the references are identical - point to the same object. With value types (i.e., primitives) it evaluates as true if the value is identical. The equals method is to return true if two objects have identical content - however, the equals method in the java.lang.Object class - the default equals method if a class does not override it - returns true only if both references point to the same object.
Let's use the following example to see what difference between these creations of string:
public class DemoStringCreation {
public static void main (String args[]) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("str1 and str2 are created by using string literal.");
System.out.println(" str1 == str2 is " + (str1 == str2));
System.out.println(" str1.equals(str2) is " + str1.equals(str2));
String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println("str3 and str4 are created by using new operator.");
System.out.println(" str3 == str4 is " + (str3 == str4));
System.out.println(" str3.equals(str4) is " + str3.equals(str4));
String str5 = "Hel"+ "lo";
String str6 = "He" + "llo";
System.out.println("str5 and str6 are created by using string constant expression.");
System.out.println(" str5 == str6 is " + (str5 == str6));
System.out.println(" str5.equals(str6) is " + str5.equals(str6));
String s = "lo";
String str7 = "Hel"+ s;
String str8 = "He" + "llo";
System.out.println("str7 is computed at runtime.");
System.out.println("str8 is created by using string constant expression.");
System.out.println(" str7 == str8 is " + (str7 == str8));
System.out.println(" str7.equals(str8) is " + str7.equals(str8));
}
}
The output result is:
str1 and str2 are created by using string literal.
str1 == str2 is true
str1.equals(str2) is true
str3 and str4 are created by using new operator.
str3 == str4 is false
str3.equals(str4) is true
str5 and str6 are created by using string constant expression.
str5 == str6 is true
str5.equals(str6) is true
str7 is computed at runtime.
str8 is created by using string constant expression.
str7 == str8 is false
str7.equals(str8) is true
The creation of two strings with the same sequence of letters without the use of the new keyword will create pointers to the same String in the Java String literal pool. The String literal pool is a way Java conserves resources.
String Literal Pool
String allocation, like all object allocation, proves costly in both time and memory. The JVM performs some trickery while instantiating string literals to increase performance and decrease memory overhead. To cut down the number of String objects created in the JVM, the String class keeps a pool of strings. Each time your code create a string literal, the JVM checks the string literal pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool. Java can make this optimization since strings are immutable and can be shared without fear of data corruption. For example
public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = "Hello";
System.out.print(str1 == str2);
}
}
The result is
true
Unfortunately, when you use
String a=new String("Hello");
a String object is created out of the String literal pool, even if an equal string already exists in the pool. Considering all that, avoid new String unless you specifically know that you need it! For example
public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = new String("Hello");
System.out.print(str1 == str2 + " ");
System.out.print(str1.equals(str2));
}
}
The result is
false true
A JVM has a string pool where it keeps at most one object of any String. String literals always refer to an object in the string pool. String objects created with the new operator do not refer to objects in the string pool but can be made to using String's intern() method. The java.lang.String.intern() returns an interned String, that is, one that has an entry in the global String pool. If the String is not already in the global String pool, then it will be added. For example
public class Program
{
public static void main(String[] args)
{
// Create three strings in three different ways.
String s1 = "Hello";
String s2 = new StringBuffer("He").append("llo").toString();
String s3 = s2.intern();
// Determine which strings are equivalent using the ==
// operator
System.out.println("s1 == s2? " + (s1 == s2));
System.out.println("s1 == s3? " + (s1 == s3));
}
}
The output is
s1 == s2? false
s1 == s3? true
There is a table always maintaining a single reference to each unique String object in the global string literal pool ever created by an instance of the runtime in order to optimize space. That means that they always have a reference to String objects in string literal pool, therefore, the string objects in the string literal pool not eligible for garbage collection.
String Literals in the Java Language Specification Third Edition
Each string literal is a reference to an instance of class String. String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions-are "interned" so as to share unique instances, using the method String.intern.
Thus, the test program consisting of the compilation unit:
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
and the compilation unit:
package other;
public class Other { static String hello = "Hello"; }
produces the output:
true true true true false true
This example illustrates six points:
Literal strings within the same class in the same package represent references to the same String object.
Literal strings within different classes in the same package represent references to the same String object.
Literal strings within different classes in different packages likewise represent references to the same String object.
Strings computed by constant expressions are computed at compile time and then treated as if they were literals.
Strings computed by concatenation at run time are newly created and therefore distinct.
The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents.
There are two ways to create a String object in Java:
Using the new operator. For example,
String str = new String("Hello");.
Using a string literal or constant expression). For example,
String str="Hello"; (string literal) or
String str="Hel" + "lo"; (string constant expression).
What is difference between these String's creations? In Java, the equals method can be considered to perform a deep comparison of the value of an object, whereas the == operator performs a shallow comparison. The equals method compares the content of two objects rather than two objects' references. The == operator with reference types (i.e., Objects) evaluates as true if the references are identical - point to the same object. With value types (i.e., primitives) it evaluates as true if the value is identical. The equals method is to return true if two objects have identical content - however, the equals method in the java.lang.Object class - the default equals method if a class does not override it - returns true only if both references point to the same object.
Let's use the following example to see what difference between these creations of string:
public class DemoStringCreation {
public static void main (String args[]) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("str1 and str2 are created by using string literal.");
System.out.println(" str1 == str2 is " + (str1 == str2));
System.out.println(" str1.equals(str2) is " + str1.equals(str2));
String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println("str3 and str4 are created by using new operator.");
System.out.println(" str3 == str4 is " + (str3 == str4));
System.out.println(" str3.equals(str4) is " + str3.equals(str4));
String str5 = "Hel"+ "lo";
String str6 = "He" + "llo";
System.out.println("str5 and str6 are created by using string constant expression.");
System.out.println(" str5 == str6 is " + (str5 == str6));
System.out.println(" str5.equals(str6) is " + str5.equals(str6));
String s = "lo";
String str7 = "Hel"+ s;
String str8 = "He" + "llo";
System.out.println("str7 is computed at runtime.");
System.out.println("str8 is created by using string constant expression.");
System.out.println(" str7 == str8 is " + (str7 == str8));
System.out.println(" str7.equals(str8) is " + str7.equals(str8));
}
}
The output result is:
str1 and str2 are created by using string literal.
str1 == str2 is true
str1.equals(str2) is true
str3 and str4 are created by using new operator.
str3 == str4 is false
str3.equals(str4) is true
str5 and str6 are created by using string constant expression.
str5 == str6 is true
str5.equals(str6) is true
str7 is computed at runtime.
str8 is created by using string constant expression.
str7 == str8 is false
str7.equals(str8) is true
The creation of two strings with the same sequence of letters without the use of the new keyword will create pointers to the same String in the Java String literal pool. The String literal pool is a way Java conserves resources.
String Literal Pool
String allocation, like all object allocation, proves costly in both time and memory. The JVM performs some trickery while instantiating string literals to increase performance and decrease memory overhead. To cut down the number of String objects created in the JVM, the String class keeps a pool of strings. Each time your code create a string literal, the JVM checks the string literal pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool. Java can make this optimization since strings are immutable and can be shared without fear of data corruption. For example
public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = "Hello";
System.out.print(str1 == str2);
}
}
The result is
true
Unfortunately, when you use
String a=new String("Hello");
a String object is created out of the String literal pool, even if an equal string already exists in the pool. Considering all that, avoid new String unless you specifically know that you need it! For example
public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = new String("Hello");
System.out.print(str1 == str2 + " ");
System.out.print(str1.equals(str2));
}
}
The result is
false true
A JVM has a string pool where it keeps at most one object of any String. String literals always refer to an object in the string pool. String objects created with the new operator do not refer to objects in the string pool but can be made to using String's intern() method. The java.lang.String.intern() returns an interned String, that is, one that has an entry in the global String pool. If the String is not already in the global String pool, then it will be added. For example
public class Program
{
public static void main(String[] args)
{
// Create three strings in three different ways.
String s1 = "Hello";
String s2 = new StringBuffer("He").append("llo").toString();
String s3 = s2.intern();
// Determine which strings are equivalent using the ==
// operator
System.out.println("s1 == s2? " + (s1 == s2));
System.out.println("s1 == s3? " + (s1 == s3));
}
}
The output is
s1 == s2? false
s1 == s3? true
There is a table always maintaining a single reference to each unique String object in the global string literal pool ever created by an instance of the runtime in order to optimize space. That means that they always have a reference to String objects in string literal pool, therefore, the string objects in the string literal pool not eligible for garbage collection.
String Literals in the Java Language Specification Third Edition
Each string literal is a reference to an instance of class String. String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions-are "interned" so as to share unique instances, using the method String.intern.
Thus, the test program consisting of the compilation unit:
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
and the compilation unit:
package other;
public class Other { static String hello = "Hello"; }
produces the output:
true true true true false true
This example illustrates six points:
Literal strings within the same class in the same package represent references to the same String object.
Literal strings within different classes in the same package represent references to the same String object.
Literal strings within different classes in different packages likewise represent references to the same String object.
Strings computed by constant expressions are computed at compile time and then treated as if they were literals.
Strings computed by concatenation at run time are newly created and therefore distinct.
The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents.
Tuesday, September 16, 2008
Add Logging at Class Load Time with Java Instrumentation
Add Logging at Class Load Time with Java Instrumentation
See: http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html
When you're trying to analyze why a program failed, a very valuable piece of information is what the program was actually doing when it failed. In many cases, this can be determined with a stack trace, but frequently that information is not available, or perhaps what you need is information about the data that was being processed at the time of failure.
Traditionally this means using a logging framework like log4j or the Java Logging API, and then writing and maintaining all necessary log statements manually. This is very tedious and error-prone, and well-suited for automation. Java 5 added the Java Instrumentation mechanism, which allows you to provide "Java agents" that can inspect and modify the byte code of the classes as they are loaded.
This article will show how to implement such a Java agent, which transparently will add entry and exit logging to all methods in all your classes with the standard Java Logging API. The example used is Hello World:public class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello World");
}
}
And here is the same program with entry and exit log statements added:import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggingHelloWorld {
final static Logger _log = Logger.getLogger(LoggingHelloWorld.class.getName());
public static void main(String args[]) {
if (_log.isLoggable(Level.INFO)) {
_log.info("> main(args=" + Arrays.asList(args) + ")");
}
System.out.println("Hello World");
if (_log.isLoggable(Level.INFO)) {
_log.info("<> main(args=[])
Hello World
2007-12-22 22:08:52 LoggingHelloWorld main
INFO: < title="blocked::http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html" href="http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html">http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html
See: http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html
When you're trying to analyze why a program failed, a very valuable piece of information is what the program was actually doing when it failed. In many cases, this can be determined with a stack trace, but frequently that information is not available, or perhaps what you need is information about the data that was being processed at the time of failure.
Traditionally this means using a logging framework like log4j or the Java Logging API, and then writing and maintaining all necessary log statements manually. This is very tedious and error-prone, and well-suited for automation. Java 5 added the Java Instrumentation mechanism, which allows you to provide "Java agents" that can inspect and modify the byte code of the classes as they are loaded.
This article will show how to implement such a Java agent, which transparently will add entry and exit logging to all methods in all your classes with the standard Java Logging API. The example used is Hello World:public class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello World");
}
}
And here is the same program with entry and exit log statements added:import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggingHelloWorld {
final static Logger _log = Logger.getLogger(LoggingHelloWorld.class.getName());
public static void main(String args[]) {
if (_log.isLoggable(Level.INFO)) {
_log.info("> main(args=" + Arrays.asList(args) + ")");
}
System.out.println("Hello World");
if (_log.isLoggable(Level.INFO)) {
_log.info("<> main(args=[])
Hello World
2007-12-22 22:08:52 LoggingHelloWorld main
INFO: < title="blocked::http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html" href="http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html">http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html
Subscribe to:
Posts (Atom)