Monday, June 01, 2020
Salesforce Layout - Clickable Address Field
Posted by sathish at 6/01/2020 11:42:00 PM 0 comments
Labels: Salesforce
Saturday, April 23, 2016
Unit Testing Log Statements
Sometimes asserting on a log statement might be the only way of validating a method call. One way of asserting log statements is to create a custom appender and attaching it to the logger to capture the logs. log4j-api provides the framework to create a custom appender.
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class CustomAppender extends AbstractAppender {
private List messages = new ArrayList<>();
public CustomAppender(String name, Filter filter, Layout layout) {
super(name, filter, layout);
}
public CustomAppender(String name, Filter filter, Layout layout, boolean ignoreExceptions) {
super(name, filter, layout, ignoreExceptions);
}
@Override
public void append(LogEvent event) {
byte[] data = getLayout().toByteArray(event);
messages.add(new String(data).trim()); // optional trim
}
@Override
public void stop() {
}
public List getMessages() {
return messages;
}
}
Following method adds the custom appender to the logger:
private void setUpLogHandler() {
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final AbstractConfiguration config = (AbstractConfiguration) ctx.getConfiguration();
// Create and add the appender
customAppender = new CustomAppender("Custom", null, PatternLayout.createDefaultLayout());
customAppender.start();
config.addAppender(customAppender);
// Create and add the logger
AppenderRef[] refs = new AppenderRef[]{AppenderRef.createAppenderRef("Custom", null, null)};
LoggerConfig loggerConfig = LoggerConfig.createLogger("false", Level.INFO, ClassUnderTest.class.getCanonicalName(), "true", refs, null, config, null);
loggerConfig.addAppender(customAppender, null, null);
config.addLogger(ClassUnderTest.class.getCanonicalName(), loggerConfig);
ctx.updateLoggers();
}
Below is an example test method which asserts on a method that logs:
@Test
public void logTest() {
setUpLogHandler();
ClassUnderTest ct = new ClassUnderTest();
ct.methodThatLogs();
assertThat(customAppender.getMessages(), hasItem("new log message"));
}
Posted by sathish at 4/23/2016 12:09:00 AM 0 comments
Thursday, April 21, 2016
Git - Rewriting Commit
Git provides an option to modify the last commit. For staging follow the normal method:
git add .After staging the files, use the
--amend option to staged files to the last commit:
git commit --amendIf no commit message is provided with
-m option the previous commit message will be prompted by default. On the other hand to amend a commit without changing its commit message use the --no-edit option.
Posted by sathish at 4/21/2016 10:23:00 PM 0 comments
Labels: git
Wednesday, April 20, 2016
Parameterized JUnit Tests
JUnitParams provides a runner - JUnitParamsRunner, to add parameterized tests in a test class. With this runner parameterized and non-parameterized test methods can be combined in the same class.
@RunWith(JUnitParamsRunner.class)
public class ParameterizedTests {
@Parameters({"1, true", "2, false"})
@Test
public void test1(int num, boolean result) {
assertThat(num == 1, is(result));
}
}
To pass in objects or null values, a separate method can be setup, which then can be added to the @Parameters annotation.
@RunWith(JUnitParamsRunner.class)
public class ParameterizedTests {
private Object[] params() {
return $(
$(1, true),
$(2, false)
);
}
@Parameters(method = "params")
@Test
public void test1(int num, boolean result) {
assertThat(num == 1, is(result));
}
}
Posted by sathish at 4/20/2016 10:09:00 PM 0 comments
Wednesday, April 13, 2016
Maven Auto Increment Version
Maven update-versions is a handy goal to increment version number of a project. This is especially useful for large multi-module maven projects.
mvn release:update-versionsThe above command prompts for the new version for each module in the project. The prompts can be avoided by using the option autoVersionSubmodules. This will set each module version to be same as the parent POM.
mvn releae:update-versions -DautoVersionSubmodules=trueThe goal can be run in non-interactive mode using batch-mode.
mvn --batch-mode release:update-versionsAbove command will auto increment the version without prompts. A specific version can also be specified:
mvn --batch-mode release:update-versions -DdevelopmentVersion=1.1-SNAPSHOT
Posted by sathish at 4/13/2016 07:43:00 PM 0 comments
Labels: maven
Saturday, September 07, 2013
Abstract Factory
The Abstract Factory pattern provides an interface that delegates creation calls to one or more concrete classes in order to deliver specific objects. Following is the definition provided for the pattern in the GoF book on Design Patterns: Abstract Factory provides an interface for creating families of related or dependent objects without specifying their concrete classes. Abstract factory relies on object composition – i.e. object creation is implemented in methods exposed in the factory methods. The intent of the pattern is to create families of related objects without having to depend on their concrete classes. First we define the interface and implementation of the object that we want to create: public interface Car { public void setDescription(String description); public void refuel(); } public class EVCar implements Car { @Override public void setDescription(String description) { // set description } @Override public void refuel() { // electric charging } } public class HybridCar implements Car { @Override public void setDescription(String description) { // set description } @Override public void refuel() { // refuel with gas } } Now we define the factories, starting with an abstract factory: public interface AbstractCarFactory { public Car createCar(); } Next the actual implementations of the factory: public class EVCarFactory implements AbstractCarFactory { @Override public Car createCar() { EVCar evCar = new EVCar(); return evCar; } } public class HybridCarFactory implements AbstractCarFactory { @Override public Car createCar() { HybridCar hybridCar = new HybridCar(); return hybridCar; } } Now let's test drive this factory: public class AbstractFactoryTest { AbstractCarFactory abstractCarFactory = null; @Test public void evCarFactoryTest() { abstractCarFactory = new EVCarFactory(); abstractCarFactory.createCar(); } @Test public void hybridCarFactoryTest() { abstractCarFactory = new HybridCarFactory(); abstractCarFactory.createCar(); } } While the pattern hides the implementation details from the client, there is always a chance that the underlying system will need to change – for example new attributes might be added to Car or AbstractCarFactory, which would mean a change to the interface that the client was relying on, thus breaking the API.
Posted by Sathish at 9/07/2013 10:58:00 AM 0 comments
Tuesday, August 13, 2013
Priority Queue
Posted by Sathish at 8/13/2013 02:10:00 AM 0 comments
Monday, March 18, 2013
Factory Method Pattern
The Factory Method Pattern encapsulates object creation by letting subclasses decide what objects to create. The creator class defines an abstract factory method that the subclasses implement to produce products.
Factory method is known as a creational pattern - it's used to construct objects such that they can be decoupled from the implementing system.
The GoF book on Design Patterns defines it as -
Define an interface for creating an object, but let the subclasses decide which class to instantitate. The Factory method lets a class defer instantiation to subclasses.
In this definition the term "interface" is used in the general sense, meaning - a concrete class implementing a method from a supertype (a class or interface).
The Factory method builds on the concept of a Simple Factory, but lets the sub-classes decide which implementation of the concrete class to use. Simple factory is a programming idiom rather than a pattern, where object creation is relegated to a method. Factory Method pattern builds on it - deferring object creation to sub-classes.
A simple factory can also be defined as a static method and is often called a static factory. This way we don’t have to instantiate an object to make use of the create method. But the disadvantage is that, we can’t subclass and change the behavior of the create method.
Example code from http://java.dzone.com/articles/design-patterns-factory. First an interface and an implementation for the product:
public interface Logger {
public void log(String message);
}
public class XmlLogger implements Logger {
@Override
public void log(String message) {
System.err.println(message);
}
}
Creator with the abstract factory method:
public abstract class AbstractLoggerCreator {
//factory method
public abstract Logger createLogger();
public Logger getLogger() {
Logger logger = new XmlLogger();
return logger;
}
}
Now the concrete creator class:
public class XmlLoggerCreator extends AbstractLoggerCreator {
@Override
public Logger createLogger() {
XmlLogger logger = new XmlLogger();
return logger;
}
}
Finally the client code to test the pattern:
public class FactoryMethodClient {
private void methodA(AbstractLoggerCreator creator) {
Logger logger = creator.createLogger();
logger.log("message");
}
public static void main(String[] args) {
AbstractLoggerCreator creator = new XmlLoggerCreator();
FactoryMethodClient client = new FactoryMethodClient();
client.methodA(creator);
}
}
Downside of the pattern is that it might be over-complicated. In a lot of cases, a simple factory pattern will work fine. The FactoryMethod just allows further decoupling, leaving it to the sub-classes of the Creator to decide which type of concrete Product to create.
Posted by sathish at 3/18/2013 01:22:00 AM 0 comments
Labels: design, design pattern, java
Thursday, March 07, 2013
Data Structures - Queue
A Queue is an example of a linear data structure - a sequential
collection, and it is a FIFO structure. Anything that's inserted
first, will be the first to leave. We need to maintain two pointers,
the start and the end. An efficient implementation of Queue performs
the operations - enqueue (insert) and dequeue (remove) - in O(1) time.
Below is a sample implementation of a Queue (Java Data Structures (2nd edition))
public class Queue {
private Object[] objArray;
private int start, end;
private boolean full;
public Queue(final int maxSize) {
objArray = new Object[maxSize];
start = end = 0;
full = false;
}
public boolean isEmpty() {
return (start == end) && !full;
}
public boolean isFull() {
return full;
}
public void insert(final Object o) {
if (!full) {
objArray[start = (++start % objArray.length)] = o;
}
if (start == end) {
full = true;
}
}
public Object remove() {
if (full) {
full = false;
} else if (isEmpty()) {
return null;
}
return objArray[end = (++end % objArray.length)];
}
public String toString() {
StringBuilder sbr = new StringBuilder();
for (int i = 0; i < objArray.length; i++) {
sbr.append(objArray[i]);
}
return sbr.toString();
}
}
Posted by sathish at 3/07/2013 12:20:00 AM 0 comments
Labels: data structures, design, java
Monday, April 26, 2010
Threads: Producer-Consumer Problem
Producer-Consumer problem is a very common question related to threads. Following is a simple solution to the problem. QueueClass represents the queue which both the Producer and Consumer has to access. The critical methods in the QueueClass - add() and remove() are synchronized in order to maintain the status quo between the Producer and Consumer threads.
import java.util.List;
import java.util.ArrayList;
public class ProducerConsumerTest {
/**
* @param args
*/
public static void main(String[] args) {
QueueClass q = new QueueClass();
Producer p = new Producer(q, 10);
Consumer c = new Consumer(q, 10);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
c.setpThread(t1);
t1.start();
t2.start();
}
}
class Producer implements Runnable {
QueueClass q;
int size;
Producer(QueueClass q, int size) {
this.q = q;
this.size = size;
}
public void run() {
int index = -1;
while(true) {
q.add(new String("" + ++index));
try {
Thread.sleep(1000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
QueueClass q;
int size;
Thread pThread;
public void setpThread(Thread pThread) {
this.pThread = pThread;
}
Consumer(QueueClass q, int size) {
this.q = q;
this.size = size;
}
public void run() {
while(true) {
q.remove();
try {
Thread.sleep(1000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
class QueueClass {
Listqueue = new ArrayList ();
int size = 10;
public synchronized void add(String s) {
if(getSize() < size) queue.add(s);
System.out.println("Added: " + queue);
try {
if(getSize() >= size) {
notifyAll();
wait();
}
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void remove() {
if(getSize() > 0) queue.remove(queue.size()-1);
System.out.println("Removed: " + queue);
try {
if(getSize() <= 0) {
notifyAll();
wait();
}
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
public synchronized int getSize() {
return queue.size();
}
}
Posted by sathish at 4/26/2010 08:51:00 AM 0 comments
Labels: java, java example, threads
Thursday, March 04, 2010
Linked List
Linked list is a fundamental data structure, which uses reference stored in each node to iterate through subsequent nodes. A linked list has many types like singly linked list, doubly linked list and circular linked list. Following is a simple bare bone implementation of singly linked list:
The base interface:
public interface LinkedList{
public boolean add(T t);
public boolean remove(T t);
public void removeAll();
public int size();
public boolean isEmpty();
}
Class representing each node:
public class LinkNode{
private LinkNodenextNode = null;
private T node = null;
public LinkNode() {
}
public LinkNode(T node) {
this.node = node;
}
public T getNode() {
return node;
}
public void setNode(T node) {
this.node = node;
}
public LinkNodegetNextNode() {
return nextNode;
}
public void setNextNode(LinkNodenextNode) {
this.nextNode = nextNode;
}
public String toString() {
return node.toString();
}
public int hashCode() {
return node.hashCode();
}
public boolean equals(LinkNodet) {
return node.equals(t.getNode());
}
}
Implementation for a singly linked list:
public class SingleLinkedListimplements LinkedList {
LinkNodeheader = null;
LinkNodelastNode = null;
public SingleLinkedList() {
}
public boolean add(T t) {
LinkNodenewNode = new LinkNode (t);
if(header == null) {
header = newNode;
}
else {
lastNode.setNextNode(newNode);
}
lastNode = newNode;
return true;
}
public boolean remove(T t) {
LinkNodetmp = header;
LinkNodeprev = null;
while(tmp != null) {
if(tmp.getNode().equals(t)) {
if(prev == null) header = null;
else if(tmp.getNextNode() != null) prev.setNextNode(tmp.getNextNode());
return true;
}
prev = tmp;
tmp = tmp.getNextNode();
}
return false;
}
public void removeAll() {
header = null;
}
public boolean isEmpty() {
return header == null;
}
public int size() {
LinkNodetmp = header;
int size = 0;
while(tmp != null) {
size++;
tmp = tmp.getNextNode();
}
return size;
}
public String toString() {
StringBuffer str = new StringBuffer("[");
LinkNodetmp = header;
while(tmp != null) {
str.append(tmp.toString());
tmp = tmp.getNextNode();
if(tmp != null) str.append(", ");
}
str.append("]");
return str.toString();
}
}
Test class which uses the singly linked list implementation:
public class LinkedListTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkedListlist = new SingleLinkedList ();
System.out.println("Is list empty? " + list.isEmpty());
list.add("1");
list.add("2");
list.add("3");
list.add("2");
list.add("2");
list.add("3");
System.out.println(list.size());
System.out.println(list);
System.out.println("Is list empty? " + list.isEmpty());
list.remove("2");
System.out.println(list.size());
System.out.println(list);
System.out.println("Is list empty? " + list.isEmpty());
list.removeAll();
System.out.println("Is list empty? " + list.isEmpty());
}
}
Posted by sathish at 3/04/2010 07:51:00 AM 0 comments
Labels: collections, java, java example, java5
Wednesday, March 03, 2010
Adapter Pattern
- The adapter acts as the middleman by receiving requests from the client and converting them into requests that make sense on the vendor classes
- The adapter implements the target interface and holds an instance of the adaptee
- The actual interface that the client needs is the target interface
- We wrap the target interface with an adaptee interface, which does the work of the target interface
- The client makes the request on the adapter, and the adapter delegates it to the adaptee interface
- The client doesn't know that the actual work was done by the adaptee
- Client and the adaptee are decoupled – neither knows about the other
- Here's how the client uses the adapter
o The client makes a request to the adapter by calling a method on it using the target interface
o The adapter translates that request into one or more calls on the adaptee using the adaptee interface
o The client receives the results of the call and never knows there is an adapter doing the translation
- The Adapter Pattern converts the interface of a class into another interface the clients expect
- Adapter lets classes work together that couldn't otherwise because of incompatible interfaces
- This decouples the client from the implemented interface,
- If the interface changes over time, the adapter encapsulates the change so that the client doesn't have to be modified each time it needs to operate against a different interface
- It is not necessary that the adapter should wrap only one adaptee – it can hold two or more adaptees that are need to implement the target interface
- There are two types of adapters
o object adapters – uses composition - the adapter is composed of adaptee
§ it can not only adapt an adaptee class, but any of its subclasses
o class adapters – uses multiple inheritance - the adapter subclasses both the target and the adaptee
§ it is committed to one specific adaptee class, but it doesn't have to reimplement the entire adaptee
§ it can also override the behavior of the adaptee, since its just subclassing
§ this cannot be used in Java since it involves multiple inheritance
- Although Decorator and Adapter patterns looks similar, they are totally different in intent
o Decorator wraps an object and adds new behavior
o Adapter wraps an object and converts it into an interface the client expects
- Following is an example of Adapter pattern. This example adapts an Enumerator to act as an Iterator
public class EnumerationAdapter implements Iterator {
Enumeration enumeration;
public EnumerationAdapter(Enumeration enumeration) {
this.enumeration = enumeration;
}
public boolean hasNext() {
enumeration.hasMoreElements();
}
public Object next() {
enumeration.nextElement();
}
public void remove() {
throw new UnsupportedOperationException();
}
}Posted by sathish at 3/03/2010 05:01:00 AM 0 comments
Labels: design, design pattern
Monday, December 14, 2009
Evolution of a Programmer
(http://www.ariel.com.au/jokes//The_Evolution_of_a_Programmer.html)
High School/Jr.High
10 PRINT "HELLO WORLD" 20 END
First year in College
program Hello(input, output) begin writeln('Hello World') end. Senior year in College
(defun hello (print (cons 'Hello (list 'World))))
New professional
#include <stdio.h> void main(void) { char *message[] = {"Hello ", "World"}; int i; for(i = 0; i < 2; ++i) printf("%s", message[i]); printf("\n"); } Seasoned professional
#include <iostream.h> #include <string.h> class string { private: int size; char *ptr; string() : size(0), ptr(new char[1]) { ptr[0] = 0; } string(const string &s) : size(s.size) { ptr = new char[size + 1]; strcpy(ptr, s.ptr); } ~string() { delete [] ptr; } friend ostream &operator <<(ostream &, const string &); string &operator=(const char *); }; ostream &operator<<(ostream &stream, const string &s) { return(stream << s.ptr); } string &string::operator=(const char *chrs) { if (this != &chrs) { delete [] ptr; size = strlen(chrs); ptr = new char[size + 1]; strcpy(ptr, chrs); } return(*this); } int main() { string str; str = "Hello World"; cout << str << endl; return(0); } Master Programmer
[ uuid(2573F8F4-CFEE-101A-9A9F-00AA00342820) ] library LHello { // bring in the master library importlib("actimp.tlb"); importlib("actexp.tlb"); // bring in my interfaces #include "pshlo.idl" [ uuid(2573F8F5-CFEE-101A-9A9F-00AA00342820) ] cotype THello { interface IHello; interface IPersistFile; }; }; [ exe, uuid(2573F890-CFEE-101A-9A9F-00AA00342820) ] module CHelloLib { // some code related header files importheader(<windows.h>); importheader(<ole2.h>); importheader(<except.hxx>); importheader("pshlo.h"); importheader("shlo.hxx"); importheader("mycls.hxx"); // needed typelibs importlib("actimp.tlb"); importlib("actexp.tlb"); importlib("thlo.tlb"); [ uuid(2573F891-CFEE-101A-9A9F-00AA00342820), aggregatable ] coclass CHello { cotype THello; }; }; #include "ipfix.hxx" extern HANDLE hEvent; class CHello : public CHelloBase { public: IPFIX(CLSID_CHello); CHello(IUnknown *pUnk); ~CHello(); HRESULT __stdcall PrintSz(LPWSTR pwszString); private: static int cObjRef; }; #include <windows.h> #include <ole2.h> #include <stdio.h> #include <stdlib.h> #include "thlo.h" #include "pshlo.h" #include "shlo.hxx" #include "mycls.hxx" int CHello::cObjRef = 0; CHello::CHello(IUnknown *pUnk) : CHelloBase(pUnk) { cObjRef++; return; } HRESULT __stdcall CHello::PrintSz(LPWSTR pwszString) { printf("%ws ", pwszString); return(ResultFromScode(S_OK)); } CHello::~CHello(void) { // when the object count goes to zero, stop the server cObjRef--; if( cObjRef == 0 ) PulseEvent(hEvent); return; } #include <windows.h> #include <ole2.h> #include "pshlo.h" #include "shlo.hxx" #include "mycls.hxx" HANDLE hEvent; int _cdecl main( int argc, char * argv[] ) { ULONG ulRef; DWORD dwRegistration; CHelloCF *pCF = new CHelloCF(); hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // Initialize the OLE libraries CoInitializeEx(NULL, COINIT_MULTITHREADED); CoRegisterClassObject(CLSID_CHello, pCF, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegistration); // wait on an event to stop WaitForSingleObject(hEvent, INFINITE); // revoke and release the class object CoRevokeClassObject(dwRegistration); ulRef = pCF->Release(); // Tell OLE we are going away. CoUninitialize(); return(0); } extern CLSID CLSID_CHello; extern UUID LIBID_CHelloLib; CLSID CLSID_CHello = { /* 2573F891-CFEE-101A-9A9F-00AA00342820 */ 0x2573F891, 0xCFEE, 0x101A, { 0x9A, 0x9F, 0x00, 0xAA, 0x00, 0x34, 0x28, 0x20 } }; UUID LIBID_CHelloLib = { /* 2573F890-CFEE-101A-9A9F-00AA00342820 */ 0x2573F890, 0xCFEE, 0x101A, { 0x9A, 0x9F, 0x00, 0xAA, 0x00, 0x34, 0x28, 0x20 } }; #include <windows.h> #include <ole2.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include "pshlo.h" #include "shlo.hxx" #include "clsid.h" int _cdecl main( int argc, char * argv[] ) { HRESULT hRslt; IHello *pHello; ULONG ulCnt; IMoniker * pmk; WCHAR wcsT[_MAX_PATH]; WCHAR wcsPath[2 * _MAX_PATH]; // get object path wcsPath[0] = '\0'; wcsT[0] = '\0'; if( argc > 1) { mbstowcs(wcsPath, argv[1], strlen(argv[1]) + 1); wcsupr(wcsPath); } else { fprintf(stderr, "Object path must be specified\n"); return(1); } // get print string if(argc > 2) mbstowcs(wcsT, argv[2], strlen(argv[2]) + 1); else wcscpy(wcsT, L"Hello World"); printf("Linking to object %ws\n", wcsPath); printf("Text String %ws\n", wcsT); // Initialize the OLE libraries hRslt = CoInitializeEx(NULL, COINIT_MULTITHREADED); if(SUCCEEDED(hRslt)) { hRslt = CreateFileMoniker(wcsPath, &pmk); if(SUCCEEDED(hRslt)) hRslt = BindMoniker(pmk, 0, IID_IHello, (void **)&pHello); if(SUCCEEDED(hRslt)) { // print a string out pHello->PrintSz(wcsT); Sleep(2000); ulCnt = pHello->Release(); } else printf("Failure to connect, status: %lx", hRslt); // Tell OLE we are going away. CoUninitialize(); } return(0); } Apprentice Hacker
#!/usr/local/bin/perl $msg="Hello, world.\n"; if ($#ARGV >= 0) { while(defined($arg=shift(@ARGV))) { $outfilename = $arg; open(FILE, ">" . $outfilename) || die "Can't write $arg: $!\n"; print (FILE $msg); close(FILE) || die "Can't close $arg: $!\n"; } } else { print ($msg); } 1; Experienced Hacker
#include <stdio.h> #define S "Hello, World\n" main(){exit(printf(S) == strlen(S) ? 0 : 1);} Seasoned Hacker
% cc -o a.out ~/src/misc/hw/hw.c % a.out
Guru Hacker
% echo "Hello, world."
New Manager
10 PRINT "HELLO WORLD" 20 END
Middle Manager
mail -s "Hello, world." bob@b12 Bob, could you please write me a program that prints "Hello, world."? I need it by tomorrow. ^D
Senior Manager
% zmail jim I need a "Hello, world." program by this afternoon.
Chief Executive
% letter letter: Command not found. % mail To: ^X ^F ^C % help mail help: Command not found. % damn! !: Event unrecognized % logout
Posted by sathish at 12/14/2009 10:17:00 AM 0 comments
Wednesday, December 09, 2009
Tuesday, June 30, 2009
Struts2 - Hello World!!
/Struts2-Example/
/index.jsp
/HelloWorld.jsp
/WEB-INF/
/web.xml
/classes/
/struts.xml
/networked/
/HelloWorld.class
/lib/
/commons-logging-1.1.jar
/freemarker-2.3.8.jar
/ognl-2.6.11.jar
/struts2-core-2.0.11.jar
/xwork-2.0.4.jar
Following three snippets provide the code for the three main components for the app.
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>Name Collector</title></head>
<body>
<h4>Enter your name: </h4>
<s:form action="HelloWorld">
<s:textfield name="name" label="Your name"/>
<s:submit/>
</s:form>
</body>
</html>
package networked;
public class HelloWorld {
private static final String GREETING = "Hello ";
public String execute() {
setCustomGreeting(GREETING + getName());
return "SUCCESS";
}
private String name, customGreeting;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getCustomGreeting() {
return this.customGreeting;
}
public void setCustomGreeting(String customGreeting) {
this.customGreeting = customGreeting;
}
}
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>HelloWorld</title></head>
<body>
<h3>Custom Greeting Page</h3>
<h4><s:property value="customGreeting"/></h4>
</body>
</html>
Example 2
struts2
org.apache.struts2.dispatcher.FilterDispatcher
struts2
/*
index.jsp
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
/HelloWorld.jsp
Posted by sathish at 6/30/2009 10:45:00 AM 0 comments
Labels: struts2
Wednesday, April 08, 2009
Eleven IT horror stories
Automatic updates
BrilliantCompany.com was growing at dot-com bubble rates. With departments popping up like daisies in spring, the IT staff was ceding desktop control to department heads because most everyone was technical anyway.
Shortly after a batch of 75 new Dell desktops arrived to populate a new product division, the network suddenly died in the middle of the day. All lights were green in infrastructure land, but performance had slowed to such a crawl that the LAN was effectively paralyzed. Some diligent sniffing and log file snooping revealed the culprit.
Turns out Windows XP’s Automatic Update had defaulted to high noon on a weekday, and all 75 machines attempted to download several hundred megs of Service Pack 2 simultaneously and individually. Instant network clog.
Solution: Centralize IT control so one somebody can be responsible for all the details. This was done in short order after I released a sprightly memo to the appropriate folks. Then, I did what I should have done earlier and set up SUS (Software Update Services), now WSUS (Windows Server Update Services), to download updates and distribute at an appropriate time and after appropriate testing against departmental OS images.
Moral: Just because your users are technical doesn’t mean they’ll behave with any more attention to detail than the average Joe. If network uptime is your responsibility, then take responsibility and manage what needs managing.
Client protection
InfoWorld reader SEnright relates a tearful tale: A mobile user called to say that his laptop was no longer functioning. After a lengthy phone conversation, during which the user initially denied anything unusual had happened, he disclosed that he had spilled an entire can of Coke on the keyboard. “He continued by telling me that he had tried to dry it with a hair dryer, but that it still would not boot. I asked him to send it back to me, and that I would have it repaired.”
But when SEnright opened the laptop’s shipping box the very next day, he had a bit of a shock. “The gentleman had not used a ‘hair dryer,’ but must have borrowed a heat gun at one of our locations, because all that was left of the keyboard was a cooled pool of molten black plastic.” Ouch.
Solution: The laptop was insured for “accidental” damage only. Since the incident, maintaining full coverage of mobile equipment has been a matter of course for SEnright.
Moral: Cover your mobile warriors. That means not only insuring their hardware, but giving them training and clear policy documents on what can and can’t be done with company hardware on the road. Further, make sure their data is backed up religiously, both when they’re at the home office and when they’re on the road.
Executive clout
Here, we’re concerned with that senior executive who just has to have full administrative rights to every machine on the network. Even though he’s about as technical as my cat--and my cat is dead.
Senior users can be dangers even without special access rights. John Schoonover, who worked for the Department of Defense on one of the largest network deployments in history during Operation Enduring Freedom was “witness to a huge lack of IQ points” in a senior manager.
According to Schoonover, military infosec installations generally follow a concept termed “the separation of red and black.” Red is simply data that has not been encrypted yet. (Danger, the world and sniffers can see you!) Black is the same data after it has been encrypted and is now ready to traverse the world. “These areas [red and black] are required to be separated by a six foot physical gap,” Schoonover says.
Our hero proceeds to follow these guidelines and deploys the network, but comes back from lunch one day to find the firewall down. Investigation shows that a senior manager “had taken the cabling from the inside router and connected to the Internet for connectivity, thus bypassing all firewall services, encryption, and -- oh yeah, that’s right -- the entire secure network with a jump straight to the Internet!”
Solution: John says they “removed the culprit’s thumbs, because if you can’t grip the cable, you can’t unplug it.” I didn’t ask for any more details.
Moral: Managing rogue senior users is an art in itself that requires diplomacy and even outright deception. In several installations I’ve renamed the Administration account something like “IT” and made “Administrator” a functionally limited account with simply more read/write access to data directories, while still blocking access to things like the Windows system directory or Unix root directories. Most times they never notice; and if they do, I’m pretty good at making up excuses why those directories remain closed off. (“Oh, that’s something Microsoft did in the last service pack. Gosh darn that Bill Gates.”)
Legal eagles hunting IT mice
Lawyers ruin everything -- including smoothly running networks. But IT managers who ignore the ever-changing legal landscape’s impact on technology do so at their peril.
I was once called in as referee among in-house counsel, senior management, and IT staff after the company was informed that child pornography had been tracked to its servers. The company didn’t know whether to aid the investigation by figuring out which employee was responsible or to just delete all the offending files immediately and most likely incur a fine but protect the firm from getting shut down.
In the end, the lawyers managed to make a deal with investigators. The company’s IT network stayed active and we tracked the lowlife down and had him arrested. Quietly.
Solution: Talk to senior management and corporate counsel about legal issues, such as corporate response to third-party audits or company responsibility for data it’s holding concerning third-parties, before they happen.
This discussion goes beyond IT-centric solutions. Management must decide whether it wants to retain all pertinent data (the best course of action for those third-party audits) or automatically delete offending data (such as whatever’s found in porn filters).
IT and management must see eye to eye on how the company will respond to law enforcement inquiries, investigations, or even raids. If Homeland Security agents believe a terrorist is masquerading as an employee and storing data on corporate servers, they can come in and pretty much take anything they want. That could put a real crimp in the style of, say, an e-business.
Developing the best course of action should involve senior management, corporate counsel, and law enforcement. The FBI is usually pretty helpful in these discussions -- and so, sometimes, is the local computer crimes department, such as the large Computer Investigation and Technology Unit division of the NYPD.
Moral: The higher you are on the IT food chain, the more such liability can spell serious trouble. If you make sure to discuss at least general legal eventualities with senior management, you’re much more likely to do yourself and your employer some real service in specific situations. If they refuse to discuss the matter, archive everything you can.
Disasters in disaster recovery
Gary Crispens reports an incident he encountered after questioning an IT director about the company’s preparedness for disaster recovery. The director responded huffily that the hot site was ready for any disaster, including the necessary space and equipment all backed by a diesel-powered generator with “plenty of fuel.”
After about a year, the company had a hurricane-related power outage that forced it to roll over to the hot site. “Sure enough, the IT Director had critical functions up and running and I could hear that generator running out back. But after about eight hours the power went out for good and all systems crashed when the generator stopped.”
It turned out that “plenty of fuel” was one 55 gallon barrel that was already half empty from the monthly testing.
Solution: A disaster recovery plan that called for fuel checks in addition to generator testing.
Moral: Disaster recovery isn’t a static issue. One plan or one policy is never perfect out of the gate. Ever. Pass such concepts by as many experienced eyes as you can and then revisit them annually or even bi-annually for refinement.
Rogue peripherals
CompUSA and the Dummies books are teaching users just enough of the tech alphabet to spell trouble.
One of my favorite stories was the network that was severely hacked by someone who came in from the outside and deleted the main Exchange message store. Firewall logs had gotten the local IT admin nowhere, so we were called in to do a little snooping around. I wish I’d thought of it, but another guy on the team had the sense to run AirSnort. He found a wide open Linksys wireless access point in about six seconds.
The internal admin insisted there was no wireless running anywhere on the network. It took some sneaker netting, but we found the rogue AP in a senior exec’s office about 20 minutes later. Seemed he saw how cheap they were at the local CompUSA and decided to plug one into the secondary network port in his office so he could use his notebook’s wireless instead of the wired connection because no wires “looks better.”
Another problem in this vein is USB. Being able to plug in a peripheral and achieve working status without the need to install drivers has rapidly spread the popularity of personal peripherals. You don’t want to get yourself get sucked into supporting things such as printers that aren’t on your official purchase list -- or external hard disks, DVD drives, sound systems, and even monitors.
Nor do you want the security risk of an employee plugging in a gig or two of empty space into any workstation’s USB port and copying important corporate information. Source code, accounting data, and historical records all can be copied quickly and then walk out in somebody’s hip pocket.
Solution: Let employees know what is and isn’t acceptable as corporate peripherals. Keep an accurate asset record of what belongs to the IT department so you can more easily find or ignore the stuff that doesn’t. And if data theft is a problem, think about protecting yourself by disabling USB drives, uninstalling CD-RW drives, or similar measures. The work you do now can save your bacon later.
Moral: Asset management isn’t just for the anal. Knowing exactly what’s supposed to be on your network is a key step to solving a wide variety of IT mysteries.
Security silliness
Security should be everyone’s job, from CTO to administrative assistant. It’s surprising how few organizations recognize this.
I think back to a time right after a fairly large network upgrade. All weekend, day and night, had been spent migrating a nightmare network from a hodgepodge of Windows 95/98/ME and even OS/2 clients with NetWare and Windows NT servers to a clean, homogenous utopia of redundant Windows 2000 Servers on the back and Windows XP Professional desktops on the front. Things hadn’t gone quite as smoothly as we’d hoped, so instead of finishing up on Sunday afternoon, we were still putting final tweaks in place on Monday morning.
After we did our last test (making sure all local tape backups were working properly) it was about noon. (Most users by now had logged in, been informed that they needed to choose a new password in accordance with our medium-strong password guidelines, and had chosen a new password.) I stumbled bleary-eyed into the lunchroom for my umpteenth caffeine fix. Chugging my Coke, I almost missed it while mincing out of the lunchroom. But it grabbed my attention from the corner of my eye and caused Coca-Cola to shoot from my schnoz like some enraged soda dragon.
“Password List.” Yes, every user’s new password along with IT and even some specific switch passwords had been printed out by a well-meaning secretary and posted in the lunchroom. After they pried my hands from her throat, she explained that she just figured it’d be easier to post them there than to answer all the phone calls when users inevitably forgot them. So she went around and collected them (in my name), built her list, and posted it.
Solution: User training. Passwords should not be regarded as obstacles but as keys for very important locks. Users must be made aware of such concepts, not simply dropped into new environments. If the secretary had been given a clue, she never would have done it, but the only training this company ever gave her was how to use Word.
Moral: Preaching may be a pain, but it can sure stop a lot of FUBAR stupidity before it gets very far.
Curiosity killed the kilobyte
These situations can vary, but have the common denominator of a user experimenting with something he knows is dangerous … and not watching what he’s doing. P. A. Dunkin relates a situation that, surprisingly, I’ve encountered myself. (Mr. Dunkin declined his family’s donut fortune in favor of becoming a sys admin for a software engineering firm.)
After a recent virus outbreak, a curious engineer decided to crack open a sample of the virus to “see what made it tick.” But instead of doing this on a PC that wasn’t connected to the LAN or even one using an operating system immune to the virus, he did neither and promptly reinfected the network.
Dunkin’s user had the good sense to come forward immediately -- the guy I had experience with didn’t even realize what he’d done so we didn’t detect the new infection until anti-virus software caught it.
Solution: For me, it was multiple areas of virus detection, both server and client. Nowadays you can even get this at the infrastructure layer and I highly recommend it. Just because a virus is killed once doesn’t mean it can’t get resurrected.
Moral: Dunkin says his users learned from the experience -- the advantage of having geek users. For many of us, however, his subsequent strategy is applicable: “I maintain an open-door anti-virus policy: No question about viruses is stupid, ever; and any time I have to send out a warning about an especially dangerous threat, I include an offer to help set up whatever measures are required, reminding them that it takes much less time to prevent an infection than to clean up after one.”
Server abuse
You can clean your server till it sparkles, but users can still find ways to abuse them -- especially on the storage front, as reader Yan Fortin relates. Fortin was having such a boring day, he was actually browsing his firewall logs simply for something to do (I hit Playboy.com in that situation, but to each his own). Suddenly, he received a user call that network file access was being denied. Another call prompted him to put down his fascinating log reading and do a little investigating.
“Lo and behold, I had five e-mails warning me that the free space on the F: network share was getting dangerously low. Unfortunately for me, I had turned off the Windows Messenger Service on my workstation, so I couldn’t receive any warning that way. Shame on me.” Indeed.
Fortin searched the drive for every file bigger than 50MB and stumbled upon a marketing user who was copying approximately 30 150MB TIFF files from a DVD to the network. “I called her to inform her that I would delete all her [expletive deleted] files, and did so right after.” Crisis over.
Solution: Fortin purchased additional hard disk space for the server right after this incident and also had a firm talk with the user about the relatively finite nature of server disk space.
Moral: Explaining things to inexperienced or even tech-phobic users may be a pain in the posterior, but it sure can save you time, trouble, and screaming managers in the long run.
Telecommuting terrors
Always remember that even telecommuters eventually come to the office. One reader relates the experience of a remote user visiting the home office and immediately killing the entire network. A little laptop investigation showed that the user had decided to configure his laptop as a DHCP server for his home network, which “suddenly made his machine the default gateway for that segment.”
Other examples include mamas and papas who genially allow their kids to play high-end games on the corporate hardware, or (worse) to surf the Internet in all those dark and fringelike nooks that teenagers like to explore on the Web. While the adults are out having dinner, the kids are home infecting the workstation, which promptly begins to spew out viruses the next time daddy either logs in or visits the office.
Solution: Perimeter defense. End-point security technologies such as Cisco’s NAC or Microsoft’s NAP are specifically designed to minimize this risk by scanning outside machines the moment they’re connected to the network. Failure to meet with specific criteria, including everything from minimal patch levels to scheduled virus scans, means the PC is dumped into a quarantine area of the network where it can be scanned, updated, and fixed without risk of harm to other nodes.
Moral: Talk to your telecommuters. Fair use policies with a little bit of disciplining oomph behind them can go a long way toward having mommy buy her precious offspring their own PC to infect rather than risking her job by letting them use hers.
Ultimate weirdness
This one won our Deepest Chuckle Award. Dave Schultz related an incident in which he tagged a note to a network laser printer informing users that if print quality suffered enough to warrant a toner cartridge replacement, they should first “shake a few times to yield a few additional copies.”
Schultz was later berated because a user suffered a work-related back injury by reading the note, then picking up the entire HP LaserJet 4000 and trying to shake the printer back and forth.
Solution: Shoot the user, he’s lame now, anyway.
Moral: Never let your blood pressure get too far into the dangerous numbers and keep a bottle of Advil handy.
(http://www.infoworld.com/print/21822)
Posted by sathish at 4/08/2009 07:48:00 AM 1 comments
Wednesday, March 11, 2009
How to be assertive
- Assertions were introduced in J2SE 1.4
- Rather than introducing it as a class library it was built into the language itself using the keyword assert
- Assertions can be used to test the following three roles:
- Precondition - a condition that the caller of a method agrees to satisfy
- Postcondition - a condition that the method itself promises to achieve
- Invariant - a condition that should always be true for a specified segment or at a specified point of a program
- An assertion has a boolean expression that if evaluated as false indicates a bug in the code
assert a !=b : "Not Equal!!"
- The message part after the : is optional, if given it is passed to the stack trace which is printed
- When an assertion fails, it means that the application has entered an incorrect state
- When the expression evaluates to false an AssertionError is thrown
- A good practice is to terminate the application when the error is thrown, because the application may start functioning inappropriately after a failure
- Assertions are disabled by default - to run an application with assertions enabled we have to give the option "-ea" or "-enableassertion"
java -ea AssertionTest
- The above command enables assertion for all classes except for the system classes
- To turn on assertion in system classes we have to use "-esa" or "-enablesystemassertions"
- To disable assertions we have to use "-da" or "-disableassertion", which is the default
- Also, we can enable or disable assertions for specific classes or packages
java -ea:com.test.ui.UIClass MainClass
java -ea:com.javacourses.tests... -da:com.javacourses.ui.phone MyClass - The ellipsis ... is part of the syntax
- Following is a sample class that uses assertion to check for invalid user input
import java.io.*;
public class AssertionTest {
public static void main(String[] args) throws IOException {
System.out.print("Enter your marital status: ");
int c = System.in.read();
switch((char)c) {
case 's': case 'S':
System.out.println("Single");
break;
case 'm': case 'M':
System.out.println("Married");
break;
case 'd': case 'D':
System.out.println("Divorced");
break;
default:
assert !true : "Invalid Option";
}
}
}
Posted by sathish at 3/11/2009 08:45:00 AM 0 comments
Labels: java
Friday, February 27, 2009
Thursday, January 22, 2009
Compiling Programmatically
Following example uses the JavaCompiler interface in Java 6 to programmatically compile a Java class:
public class CompilerExample {
public static void main(String[] args) {
String fileToCompile = "test.java"
javax.tools.JavaCompiler compiler = javax.tools.ToolProvider.getSystemJavaCompiler();
int compilationResult = compiler.run(null, null, null, fileToCompile);
if (compilationResult == 0) {
System.out.println("Compilation is successful");
} else {
System.out.println("Compilation Failed");
}
}
}
Posted by sathish at 1/22/2009 05:49:00 AM 0 comments