Tuesday, May 14, 2013

Toastmaster Speech #2 – An Introduction to Jenkins Continuous Integration Server

Time Limits: 6/7/8 mins

Actual Time Taken: 10 min 02 secs.

Following is the content of the speech:

Jenkins

1. What is Jenkins?

a. It’s a continuous integration server.

b. It is a fork of another CI server project Hudson (started by Koshiko Kawaguchi of erstwhile Sun Microsystems).

c. It is free and open source.

2. Hallmarks of Jenkins CI Server:

1. Automates builds via build triggers.

2. Automates running test suites. Fails the build if test fails. Trending of test failures by builds.

3. Encourages regular commits to the version control

4. Builds on each commit

5. Fast builds – build the module and run unit tests per module. Jenkins even supports clustering and can send the builds for different modules to different nodes in the cluster thus enabling “parallel” builds.

6. Dashboard – web based dashboard for viewing results and other notification methods like sending emails etc.

3. Why Jenkins?

a. All CI servers can poll a version control repo and execute compile and test.

b. Jenkins stands-out due to its easy-to-use web UI (with context sensitive help at each UI control level) and its extensive plugin ecosystem.

c. Due to its plug-in based ecosystem, it integrates with most of the popular version control repos, run builds for multiple languages, and view a host of valuable reports about your code.

4. How it works?

a. Jenkins supports both Ant and Maven build tools.

b. Out of the box Jenkins supports 2 version control repos: CVS and SVN.

c. Jenkin Job – You need to define a job to build a certain project. The important items you need to define are:

i. Source code management

1. Which version control branch, tag or label you are building the source code from. This is the “integration” in the CI as your team will be constantly adding new code to version control.

ii. Build triggers – when should the source code be built? This is the “continuous” of the CI.

1. Periodically – say once a day.

2. Poll SCM – set a duration say every 15 mins (specified as cron-like expresssion). If there is a commit that happened since the last poll the build will be executed.

iii. Build – what build goals/targets of the build script to execute.

d. We can have multiple jobs for the same project executing different parts of the build lifecycle. For example, we can have another job that executes once a day and executes the complete integration test suite on the build.

5. Jenkins Dashboard

a. Last Success(S) – status of the latest build

b. Weather (W) – overall health of the job – how many times build failed, whether the tests passed, and other scenarios depending on configured plugins.

6. Execute a build – can be either done manually or automatically (if polling SCM option selected).

7. Report – We can view the test reports for tests executed (triggered via Jenkins)

8. Plugin Manager – Plugins for code metrics tooling are available:

a. Checkstyle – enforces good coding guidelines.

b. FindBugs

9. Conclusion

•Jenkins an extensible CI server tool with easy to use UI and very easy to deploy.

•Use of CI server like Jenkins will go a long way in improving the quality of the software in an organization.

Saturday, May 11, 2013

Dell XPS 14 Ultrabook Review

Recently I got myself another notebook and for the first time I am trying an ultrabook – the dell xps 14 ultrabook base model which comes with i5 dual core 1.7 GHz processor, 4 GB RAM and 32GB SSD + 500 GB (5400 RPM) HDD.

The configuration is pretty decent for programming and everyday computing purposes but what is most attractive is the build quality – its aluminum body and slim overalls with the 1600x900 resolution screen for a 14” size is a pretty attractive aspect of this ultrabook. From the specs I was expecting this computer to be slow but I am plesantly surprised that over and above the processor the build of the system does make a BIG difference in the overall performance of your system. It is pretty close in look to a macbook pro and though it is not that light weight the feel of using this system is so good that I think this is the best laptop I have ever owned or even had (it surpasses my work laptop which is a dell latitude e6430).

I could not be more happy. It’s a great laptop/ultrabook to have. Especially I got this in a great deal (a refurbished one at $470 when the new ones with same config are from $800-$1000).

Tuesday, March 26, 2013

Toastmaster’s Table Topics – Life as an Object

Introduction to the theme – Life as an Object:

Spring is around the corner. Most of us will have some plans for doing stuff like cleaning their homes, to go on some vacation, to throw parties, to do other outdoor activities and get healthy.

Consider for a moment if we were not living beings - consider if we were lifeless objects like a Pen for instance. Now consider if the Pen had a mind of its own with which it can think just as we humans do.

In the table topics today, each of the respondents to the table topics will lend their voice to an object which they pick from the grab bag of objects i have. They can then tell us about their life as that Object in general or what they think (as that object) about spring time.

So let the fun begin... may i have volunteers please.

Objects options:
Pen
PC Mouse
Keyboard
Laptop
Chair
Door

etc..

Tuesday, March 19, 2013

Toastmaster’s speech 1 – Virtual Networks

Speech contents are below:

 

Speech – Virtual Networks

1. What is Virtualization?

a. Benefits: Run multiple OS on single server (hardware consolidation – 80% greater utilization), power savings, rack space saving, efficiency in maintenance and deploying patches, HA

b. Savings - > $1500 per server virtualized.

c. Types – Server, Storage (VMFS datastore), Network

2. Software Defined Datacenters – caters to capacity elasticity, on-demand application provisioning, policy based provisioning and automated operations management.

3. Types of Hypervisors

a. Type 1- Bare metal (ESXi, Hyper-v, XenServer)

b. Type 2 – Hypervisor within OS (VMware Workstation, MS VirtualServer)

c. ESXi – 32 MB footprint.

4. Virtual Network Components:

a. vSS

b. vDS

c. Port/Port group – VM Kernel, VM Port group

d. VLAN

e. Trunk port

f. Access port

g. Network Interface card team

h. Virtual network adapters – vmxnet adapters 1Gbps – inside guest OS.

5. Virtual Switch functions –

a. VM to VM on same host

b. Vmknic for vMotion, iSCSI/NFS storage access etc

c. VM to VM on different hosts

d. VM to physical host

6. Similarities to a physical switch –

a. L2 switch

b. MAC table

c. Supports VLAN

d. Supports trunking

e. Fixed number of ports (as specified) - 8, 24 … 4088

7. Dissimilarities to a physical switch –

a. vSwitch cannot be connected to vSwitch – so no looping – so no need for STP

b. vSwitch knows the MACs of VMs connected – so no need to learn MACs.

c. vSwitch cannot route traffic from one NIC to another NIC.

d. No telnet service.

8. Port groups –

a. VM Kernel port – traffic from vmknics on host

b. VM Port groups – traffic of VMs

9. Uplinks –

a. Required to connect to physical switch.

b. vSwitch can have multiple uplinks.

c. No uplink can be shared by 2 vSwitches.

d. Max 32 uplinks on host

e. vSwitch without uplink – internal-only vSwitch

10. NIC Team – 2 or more uplinks on a vSwitch. Provides load balancing and failover (Active/passive)

11. VM Port group – multiple vNICs, does not have IP addresses.

12. VLAN – can reduce number of vSwitches and uplinks required. ID 0 – 4094.

13. Switch port connected to uplink using multiple VLANs must be trunk port.

14. Distributed vSwitches – spans hosts, config change on dvPort group will be pushed to all member hosts by vCenter.

15. Conclusion – Virtual networking aids server virtualization initiatives and thus contributes to the benefits incurred from adopting virtualization.

 

I was only able to cover up to 4.a and then 15 and that itself put me in red @ 6 min+.

Friday, March 15, 2013

Java EE 6 - Part 8 - Transactions

Project: EJB31-ejb


package helloworld.beans;

import helloworld.interceptors.PMInterceptor;
import helloworld.vo.GreetingRequest;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.LocalBean;
import javax.ejb.Schedule;
import javax.ejb.Startup;
import javax.ejb.Timer;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.interceptor.Interceptors;

/**
 * This is a stateless bean using EJB timer service.
 *
 * @author rwatsh
 */
@Singleton
@LocalBean
@Startup
public class AutomaticSayHelloBean {

    @EJB
    private SingletonHelloWorldBean singletonHelloWorldBean;
    private int timerNotifications;
    private boolean cancelTimer = false;

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
    /**
     * Using schedule will cause a timer notification to occur every 5 seconds.
     */
    @Interceptors(PMInterceptor.class)
    @Schedule(second = "*/5", minute = "*", hour = "*")
    public void sayHello(Timer timer) {
        if (!cancelTimer) {
            GreetingRequest request = singletonHelloWorldBean.sayHello();
            System.out.println("AutomaticSayHelloBean.sayHello:- " + request);
            timerNotifications++;
        } else {
            timer.cancel();
            System.out.println("AutomaticSayHelloBean.sayHello: canceled timer");
        }
    }

    public int getNotificationCount() {
        return timerNotifications;
    }

    @TransactionAttribute(TransactionAttributeType.MANDATORY)
    public void cancelTimer() {
        this.cancelTimer = true;
    }
}

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

package helloworld.beans;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.transaction.UserTransaction;

/**
 * Bean implementation for controlling the timer service EJB.
 *
 * @author rwatsh
 */
@TransactionManagement(TransactionManagementType.BEAN)
@Stateless
public class AutomaticManagerBean implements AutomaticManagerBeanRemote {
    @EJB
    private AutomaticSayHelloBean automaticSayHelloBean;
    @Resource
    private TimerService timerService;
    private int threshold;
    @Resource SessionContext context;
   
    @Override
    public void manageTimer(int interval, int threshold) {
        this.threshold= threshold;
        int currentCount = automaticSayHelloBean.getNotificationCount();
        if (currentCount >= threshold){
            try {
                //automaticSayHelloBean.cancelTimer();
                cancelSayHelloTimer();
            } catch (Exception ex) {
                Logger.getLogger(AutomaticManagerBean.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            timerService.createIntervalTimer(interval, interval, null);
        }
    }

    @Override
    @Timeout
    public void monitorAutomaticTimer(Timer timer) {      
        int currentCount = automaticSayHelloBean.getNotificationCount();
        if (currentCount >= threshold) {
            try {
                //automaticSayHelloBean.cancelTimer();
                cancelSayHelloTimer();
            } catch (Exception ex) {
                Logger.getLogger(AutomaticManagerBean.class.getName()).log(Level.SEVERE, null, ex);
            }
            timer.cancel();
        }
    }
   
    private void cancelSayHelloTimer() throws Exception {
        UserTransaction ut = context.getUserTransaction();
        ut.begin();
        automaticSayHelloBean.cancelTimer();
        ut.commit();
    }

}

Project: EJB31-app-client
package ejb31;

import helloworld.beans.AutomaticManagerBeanRemote;
import javax.ejb.EJB;

/**
 * Test the automatic timer bean through its session facade
 * AutomaticManagerBean.
 *
 * @author rwatsh
 */
public class MaMApp {

    @EJB
    private static AutomaticManagerBeanRemote automaticManagerBean;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        automaticManagerBean.manageTimer(1000 * 60, 50);
        System.out.println("MaMApp.main: started management process");
    }
}

Java EE 6 - Part 7 - Writing Asynchronous Session Beans

This is a very useful enhancement in EJB 3.1 that lets the client make a server method call asynchronously.

In the past we needed to write a lot of code to achieve the same result. The client used to create a temporary JMS queue destination and pass it to the server in the remote method call and the server did its task asynchronously and used the temporary queue to send its response back to client. This has now been taken care of by Java EE 6 framework with the introduction of the @Asynchronous annotations for session beans.

Project: EJB31-Common


package helloworld.beans;

import java.util.concurrent.Future;
import javax.ejb.Remote;

/**
 * Interface for the asynch session bean.
 *
 * @author rwatsh
 */
@Remote
public interface HelloEjbAsynchronousRemote {

    Future ejbAsynchronousSayHello(String name);
   
}

Project: EJB31-ejb

package helloworld.beans;

import java.util.Date;
import java.util.concurrent.Future;
import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;

/**
 * Stateless session bean with a long running task executed asynchronously.
 *
 * @author rwatsh
 */
@Stateless
public class HelloEjbAsynchronous implements HelloEjbAsynchronousRemote {

    @Asynchronous
    @Override
    public Future ejbAsynchronousSayHello(String name) {
        System.out.println(new Date().toString() + " - Begin - HelloEjbAsynchronous.ejbAsynchronousSayHello: " + name);

        // simulate some delay
        try {
            Thread.sleep(50000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(new Date().toString() + " - End - HelloEjbAsynchronous.ejbAsynchronousSayHello: " + name);

        return new AsyncResult("Hello " + name);
    }
 }


Project: StandAloneApp

package standaloneapp;

import helloworld.beans.HelloEjbAsynchronousRemote;
import java.util.concurrent.Future;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * This client can be a SwingWorker waiting for server task to complete and
 * respond asynchronously while the client carries on with other UI tasks.
 *
 * @author rwatsh
 */
public class AsyncClient {

    private static HelloEjbAsynchronousRemote helloWorldBean;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        System.err.println("standaloneapp.Main.main: Stand-alone App started");
        String jndiPath = "java:global/EJB31/EJB31-ejb/HelloEjbAsynchronous";
        try {
            Context ctx = new InitialContext();
            System.out.println("standaloneapp.Main.main: looking up bean at: "
                    + jndiPath);
            helloWorldBean = (HelloEjbAsynchronousRemote) ctx.lookup(jndiPath);
            System.out.println("standaloneapp.Main.main: found HelloWorldBean: "
                    + helloWorldBean);
            System.out.println("standaloneapp.Main.main: calling sayHello");

            Future future = helloWorldBean.ejbAsynchronousSayHello("Watsh");

            while (!future.isDone()) {
                Thread.sleep(10000);
                System.out.println("Doing some other client tasks and waiting for server to respond");
            }

            String greeting = (String) future.get();

            System.out.println("standaloneapp.Main.main: HelloWorldBean said: "
                    + greeting);
        } catch (NamingException ex) {
            System.err.println(
                    "standaloneapp.Main.main: Could not find HelloWorldBeanRemote");
            System.err.println("standaloneapp.Main.main: JNDI path used for lookup: " + jndiPath);
            ex.printStackTrace();
        }
    }
}



Java EE 6 - Part 6 - Writing EJB TimerService and Interceptors

Project: EJB31-Common


package helloworld.beans;

import javax.ejb.Remote;
import javax.ejb.Timer;

/**
 * Interface to manage the EJB timer service.
 *
 * @author rwatsh
 */
@Remote
public interface AutomaticManagerBeanRemote {
    public void manageTimer(int interval, int threshold);

    void monitorAutomaticTimer(Timer timer);
}

Project:EJB31-ejb


package helloworld.beans;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;

/**
 * Bean implementation for controlling the timer service EJB.
 *
 * @author rwatsh
 */
@Stateless
public class AutomaticManagerBean implements AutomaticManagerBeanRemote {
    @EJB
    private AutomaticSayHelloBean automaticSayHelloBean;
    @Resource
    private TimerService timerService;
    private int threshold;
 
    @Override
    public void manageTimer(int interval, int threshold) {
        this.threshold= threshold;
        int currentCount = automaticSayHelloBean.getNotificationCount();
        if (currentCount >= threshold){
            automaticSayHelloBean.cancelTimer();
        } else {
            timerService.createIntervalTimer(interval, interval, null);
        }
    }
 
 

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")

    @Override
    @Timeout
    public void monitorAutomaticTimer(Timer timer) {      
        int currentCount = automaticSayHelloBean.getNotificationCount();
        if (currentCount >= threshold) {
            automaticSayHelloBean.cancelTimer();
            timer.cancel();
        }
    }

}
-------------------------
package helloworld.beans;

import helloworld.interceptors.PMInterceptor;
import helloworld.vo.GreetingRequest;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.LocalBean;
import javax.ejb.Schedule;
import javax.ejb.Startup;
import javax.ejb.Timer;
import javax.interceptor.Interceptors;

/**
 * This is a stateless bean using EJB timer service.
 *
 * @author rwatsh
 */
@Singleton
@LocalBean
@Startup
public class AutomaticSayHelloBean {

    @EJB
    private SingletonHelloWorldBean singletonHelloWorldBean;
    private int timerNotifications;
    private boolean cancelTimer = false;

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
    /**
     * Using schedule will cause a timer notification to occur every 5 seconds.
     */
    @Interceptors(PMInterceptor.class)
    @Schedule(second = "*/5", minute = "*", hour = "*")
    public void sayHello(Timer timer) {
        if (!cancelTimer) {
            GreetingRequest request = singletonHelloWorldBean.sayHello();
            System.out.println("AutomaticSayHelloBean.sayHello:- " + request);
            timerNotifications++;
        } else {
            timer.cancel();
            System.out.println("AutomaticSayHelloBean.sayHello: canceled timer");
        }
    }

    public int getNotificationCount() {
        return timerNotifications;
    }

    public void cancelTimer() {
        this.cancelTimer = true;
    }
}

---------------------
package helloworld.interceptors;

import javax.interceptor.AroundTimeout;
import javax.interceptor.InvocationContext;

/**
 * Interceptor to monitor invocations of a method.
 *
 * @author rwatsh
 */
public class PMInterceptor {

    private long numberOfInvocations;

    @AroundTimeout
    public Object monitorInvocations(InvocationContext ic) throws Exception {
        try {
            Object returnValue = ic.proceed();
            numberOfInvocations++;
            System.out.println("PMInterceptor.monitorInvocations: invocation count -" + numberOfInvocations);
            return returnValue;
        } catch (Exception ex) {
            System.err.println("PMInterceptor.monitorInvocations: error occurred -" + ex);
        }
        return null;
    }
}
------------------------
Project: EJB31-app-client

package ejb31;

import helloworld.beans.AutomaticManagerBeanRemote;
import javax.ejb.EJB;

/**
 * Test the automatic timer bean through its session facade
 * AutomaticManagerBean.
 *
 * @author rwatsh
 */
public class MaMApp {

    @EJB
    private static AutomaticManagerBeanRemote automaticManagerBean;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        automaticManagerBean.manageTimer(1000 * 60, 50);
        System.out.println("MaMApp.main: started management process");
    }
}

Output:
INFO: TimeBasedHelloWorldBean.postConstruct
INFO: SingletonHelloWorldBean.postConstruct
INFO: AutomaticSayHelloBean.sayHello:- helloworld.vo.GreetingRequest [requestTime=3/15/13 10:49 AM, greeting=Good Morning]
INFO: PMInterceptor.monitorInvocations: invocation count -1
INFO: AutomaticSayHelloBean.sayHello:- helloworld.vo.GreetingRequest [requestTime=3/15/13 10:49 AM, greeting=Good Morning]
INFO: PMInterceptor.monitorInvocations: invocation count -2
INFO: AutomaticSayHelloBean.sayHello:- helloworld.vo.GreetingRequest [requestTime=3/15/13 10:49 AM, greeting=Good Morning]
INFO: PMInterceptor.monitorInvocations: invocation count -3
.....
INFO: helloworld.beans.SingletonHelloWorldBean: @PreDestroy

Java EE 6 - Part 5 - Writing Message Driven Beans

Project: EJB31-Common

package helloworld.beans;

import helloworld.vo.GreetingRequest;
import javax.ejb.Remote;

/**
 *
 * @author rwatsh
 */
@Remote
public interface MessageFacadeRemote {

    GreetingRequest sayHello();
   
}


Project: EJB31-ejb

package helloworld.beans;

import helloworld.vo.GreetingRequest;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.Session;

/**
 * Message Facade bean that produces message.
 * @author rwatsh
 */
@Stateless
public class MessageFacade implements MessageFacadeRemote {

    @Resource(mappedName = "jms/HelloWorldQueue")
    private Queue helloWorldQueue;
    @Resource(mappedName = "jms/HelloWorldQueueFactory")
    private ConnectionFactory helloWorldQueueFactory;
    @EJB
    private SingletonHelloWorldBean singletonHelloWorldBean;

    private ObjectMessage createJMSMessageForjmsHelloWorldQueue(Session session, Serializable messageData) throws JMSException {
        // TODO create and populate message to send
        ObjectMessage om = session.createObjectMessage(messageData);
        return om;
    }

    private void sendJMSMessageToHelloWorldQueue(Serializable messageData) throws JMSException {
        Connection connection = null;
        Session session = null;
        try {
            connection = helloWorldQueueFactory.createConnection();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer messageProducer = session.createProducer(helloWorldQueue);
            messageProducer.send(createJMSMessageForjmsHelloWorldQueue(session, messageData));
        } finally {
            if (session != null) {
                try {
                    session.close();
                } catch (JMSException e) {
                    Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Cannot close session", e);
                }
            }
            if (connection != null) {
                connection.close();
            }
        }
    }

    @Override
    public GreetingRequest sayHello() {
        GreetingRequest result = singletonHelloWorldBean.sayHello();
        try {
            sendJMSMessageToHelloWorldQueue(result);
            System.out.println("MessageFacade.sayHello: sent message - " + result);
        } catch (JMSException ex) {
            System.err.println("MessageFacade.sayHello: error sending message - "
                    + ex);
        }
        return result;
    }
}



package helloworld.beans;

import helloworld.vo.GreetingRequest;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage;

/**
 * MDB that consumes the message.
 * @author rwatsh
 */
@MessageDriven(mappedName = "jms/HelloWorldQueue", activationConfig = {
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class HelloWorldMDB implements MessageListener {

    public HelloWorldMDB() {
    }

    @PostConstruct
    private void postConstruct() {
        System.out.println("HelloWorldMDB: @PostConstruct");
    }

    @Override
    public void onMessage(Message message) {
        if (message instanceof TextMessage) {
            try {
                TextMessage textMessage = (TextMessage) message;
                String messageValue = textMessage.getText();
                System.out.println("HelloWorldMDB.onMessage: received text message - " + messageValue);
            } catch (JMSException ex) {
                Logger.getLogger(HelloWorldMDB.class.getName()).log(Level.SEVERE, null, ex);
            }

        } else if (message instanceof ObjectMessage) {
            try {
                ObjectMessage objMessage = (ObjectMessage) message;
                Object contents = objMessage.getObject();
                if (contents instanceof GreetingRequest) {
                    String messageValue = contents.toString();
                    System.out.println("HelloWorldMDB.onMessage: received object message - " + messageValue);
                }
            } catch (JMSException ex) {
            }

        } else {
//do nothing
        }
    }

    @PreDestroy
    private void destroy() {
        System.out.println("HelloWorldMDB: @PreDestroy");
    }
}

Project: EJB31-app-client

package ejb31;

import helloworld.beans.MessageFacadeRemote;
import helloworld.vo.GreetingRequest;
import javax.ejb.EJB;

/**
 * Message facade tester which triggers the facade to send message to MDB.
 *
 * @author rwatsh
 */
public class MessageFacadeTest {

    @EJB
    private static MessageFacadeRemote messageFacade;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        GreetingRequest request = messageFacade.sayHello();
        System.out.println("MessageFacadeTest.main: facade said - "
                + request);
    }
}



Java EE 6 - Part 4 - Writing JMS Message Producers

1. Create JMS resources - QueueConnectionFactory and Queue. 

For glassfish, it is done in the glassfish-resources.xml file. Netbeans puts in /setup folder (Right click App and select New > Other > Glassfish > JMS Resource. Do it twice, once to add Admin Object Resource and then to add Connector Object Resource.



2. Create MessageProducerApp client.
Project: EJB31-app-client


package ejb31;

import helloworld.beans.SingletonHelloWorldBeanRemote;
import helloworld.vo.GreetingRequest;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * The message producer.
 * @author rwatsh
 */
public class MessageProducerApp {

    private static Message createJMSMessageForjmsHelloWorldQueue(Session session, Object messageData) throws JMSException {
        // TODO create and populate message to send
        TextMessage tm = session.createTextMessage();
        tm.setText(messageData.toString());
        return tm;
    }

    private static void sendJMSMessageToHelloWorldQueue(Object messageData) throws NamingException, JMSException {
        Context c = new InitialContext();
        ConnectionFactory cf = (ConnectionFactory) c.lookup("jms/HelloWorldQueueFactory");
        Connection conn = null;
        Session s = null;
        try {
            conn = cf.createConnection();
            s = conn.createSession(false, s.AUTO_ACKNOWLEDGE);
            Destination destination = (Destination) c.lookup("jms/HelloWorldQueue");
            MessageProducer mp = s.createProducer(destination);
            mp.send(createJMSMessageForjmsHelloWorldQueue(s, messageData));
        } finally {
            if (s != null) {
                try {
                    s.close();
                } catch (JMSException e) {
                    System.err.println("Cannot close session - " + e);
                }
            }
            if (conn != null) {
                conn.close();
            }
        }
    }

    private static SingletonHelloWorldBeanRemote lookupSingletonHelloWorldBeanRemote() {
        try {
            Context c = new InitialContext();
            return (SingletonHelloWorldBeanRemote) c.lookup("java:global/EJB31/EJB31-ejb/SingletonHelloWorldBean");
        } catch (NamingException ne) {
            ne.printStackTrace();
            throw new RuntimeException(ne);
        }
    }

    public static void main(String[] args) {
        SingletonHelloWorldBeanRemote hwr = lookupSingletonHelloWorldBeanRemote();
        GreetingRequest result = hwr.sayHello();
        String resultStr = result.toString();
        try {
            sendJMSMessageToHelloWorldQueue(resultStr);
            System.out.println("MessageProducerApp.main: sent message - " + resultStr);
        } catch (Exception ex) {
            System.err.println("MessageProducerApp.main: failed to send message - " + ex);
        }

    }
}


Java EE 6 - Part 3 - Writing Singleton Session Beans

Project: EJB31-Common

package helloworld.beans;

import helloworld.vo.GreetingRequest;
import javax.ejb.Remote;

/**
 * Remote interface for singleton bean.
 * @author rwatsh
 */
@Remote
public interface SingletonHelloWorldBeanRemote {

    GreetingRequest sayHello();

    GreetingRequest[] auditRequests();
 
}

Project: EJB31-ejb

package helloworld.beans;

import helloworld.vo.GreetingRequest;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.ejb.Singleton;

/**
 * Singleton bean implementation.
 * Note: It depends on the TimeBasedHelloWorldBean (not shown in this post) which is
 * another singleton bean. The TimeBasedHelloWorldBean will be initialized before this bean.
 * @author rwatsh
 */
@Singleton
@DependsOn("TimeBasedHelloWorldBean")
public class SingletonHelloWorldBean implements SingletonHelloWorldBeanRemote {

    @EJB
    private TimeBasedHelloWorldBean timeBasedHelloWorldBean;
    private List greetingRequests;

    public SingletonHelloWorldBean() {
        greetingRequests = new ArrayList();
    }
    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")

    @Override
    public GreetingRequest sayHello() {
        String greeting = timeBasedHelloWorldBean.sayHello();
        GreetingRequest request = new GreetingRequest(greeting);
        greetingRequests.add(request);
        return request;
    }

    @Override
    public GreetingRequest[] auditRequests() {
        return greetingRequests.toArray(new GreetingRequest[]{});
    }

    @PreDestroy
    private void destroy() {
        System.out.println("helloworld.beans.SingletonHelloWorldBean: @PreDestroy");
        for (GreetingRequest gr : greetingRequests) {
            System.out.println(gr);
        }
        greetingRequests = null;
    }
}

Project: StandAloneApp

package standaloneapp;

import helloworld.beans.SingletonHelloWorldBeanRemote;
import helloworld.vo.GreetingRequest;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * Singleton bean test client.
 * @author rwatsh
 */
public class SingletonHelloWorldBeanTest {

    private static SingletonHelloWorldBeanRemote helloWorldBean;

    public static void main(String[] args) {
        System.err.println("standaloneapp.Main.main: Stand-alone App started");
        String jndiPath = "java:global/EJB31/EJB31-ejb/SingletonHelloWorldBean";
        try {
            Context ctx = new InitialContext();
            System.out.println("standaloneapp.Main.main: looking up bean at: "
                    + jndiPath);
            helloWorldBean = (SingletonHelloWorldBeanRemote) ctx.lookup(jndiPath);
            System.out.println("standaloneapp.Main.main: found HelloWorldBean: "
                    + helloWorldBean);
            System.out.println("standaloneapp.Main.main: calling sayHello");
            GreetingRequest greeting = helloWorldBean.sayHello();
            System.out.println("standaloneapp.Main.main: HelloWorldBean said: "
                    + greeting);

            GreetingRequest[] audit = helloWorldBean.auditRequests();
            System.out.println("SingletonHelloWorldBeanTest.main: number of sayHello requests made on Singleton: " + audit.length);
        } catch (NamingException ex) {
            System.err.println(
                    "standaloneapp.Main.main: Could not find HelloWorldBeanRemote");
            System.err.println("standaloneapp.Main.main: JNDI path used for lookup: " + jndiPath);
            ex.printStackTrace();
        }
    }
}


Java EE 6 - Part 2 - Writing Stateful Session Beans

Below is an example program using Java EE 6 APIs for Stateful Session beans.

This example shows the client using JNDI lookup directly to access the session bean remote proxy instance. The other way is to use @EJB or using CDI's @Inject

Project: EJB31-Common
import helloworld.vo.GreetingRequest;
import javax.ejb.Remote;

/**
 * Remote interface for stateful session bean.
 *
 * @author rwatsh
 */
@Remote
public interface StatefulHelloWorldBeanRemote {

    GreetingRequest sayHello();

    GreetingRequest[] sayGoodBye();
    
}
--------------

package helloworld.vo;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Calendar;

/**
 * Serializable type which holds the session state.
 *
 * @author rwatsh
 */
public class GreetingRequest implements Serializable {

    private Calendar requestTime;
    private String greeting;

    public GreetingRequest(String greet) {
        requestTime = Calendar.getInstance();
        greeting = greet;
    }

    public String toString() {
        SimpleDateFormat df = new SimpleDateFormat();
        String ds = df.format(requestTime.getTime());
        return "helloworld.vo.GreetingRequest [requestTime=" + ds + ", greeting=" + greeting + "]";
    }
}
----------------------
Project: EJB31-ejb
package helloworld.beans;

import helloworld.vo.GreetingRequest;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Remove;
import javax.ejb.Stateful;

/**
 * This is the stateful session bean implementation. 
 * Requires EJB31-Common.jar in its build path.
 *
 * @author rwatsh
 */
@Stateful
public class StatefulHelloWorldBean implements StatefulHelloWorldBeanRemote {
    private List greetingRequests;

    public StatefulHelloWorldBean() {
        greetingRequests = new ArrayList();
    }

    @Override
    public GreetingRequest sayHello() {
        String greeting = "Hello EJB World";
        GreetingRequest request = new GreetingRequest(greeting);
        greetingRequests.add(request);
        return request;
    }

    @Override
    @Remove
    public GreetingRequest[] sayGoodBye() {
        return greetingRequests.toArray(new GreetingRequest[]{});
    }
}

Project: StandAloneApp
package standaloneapp;

import helloworld.beans.StatefulHelloWorldBeanRemote;
import helloworld.vo.GreetingRequest;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * A standalone Java application client to execute the EJB.
 * Note: it requires the appserver-rt.jar and the EJB31-Common.jar in its build path.
 *
 * @author rwatsh
 */
public class StatefulHelloWorldBeanTest {

    private static StatefulHelloWorldBeanRemote helloWorldBean;

    public static void main(String[] args) {
        System.err.println("standaloneapp.Main.main: Stand-alone App started");
        String jndiPath = "java:global/EJB31/EJB31-ejb/StatefulHelloWorldBean";
        try {
            Context ctx = new InitialContext();
            System.out.println("standaloneapp.Main.main: looking up bean at: "
                    + jndiPath);
            helloWorldBean = (StatefulHelloWorldBeanRemote) ctx.lookup(jndiPath);
            System.out.println("standaloneapp.Main.main: found HelloWorldBean: "
                    + helloWorldBean);
            System.out.println("standaloneapp.Main.main: calling sayHello");
            GreetingRequest greeting = helloWorldBean.sayHello();
            System.out.println("standaloneapp.Main.main: HelloWorldBean said: "
                    + greeting);
            GreetingRequest [] greetings = helloWorldBean.sayGoodBye();
        } catch (NamingException ex) {
            System.err.println(
                    "standaloneapp.Main.main: Could not find HelloWorldBeanRemote");
            System.err.println("standaloneapp.Main.main: JNDI path used for lookup: " + jndiPath);
            ex.printStackTrace();
        }
    }
}

Thursday, March 14, 2013

Java EE 6 - Part 1 - Writing Stateless Session Beans

EJB 3.1 Session Beans types:
  1. Stateless - pooled instances 
  2. Stateful - dedicated instance to a client
  3. Singleton - Only 1 instance per application per JVM instance
Following is some sample code for writing a stateful session bean (stateless is similar) - used Netbeans 7.3 with Glassfish v3 3.1.2:
  1. Create an AccountCommon project.
  2. Create an AccountEJB project as EJB Module or EJB Appplication.
    1. Add a stateful session bean class - AccountBean.
    2. Select the AccountCommon project as the project in which to create the AccountBeanRemote interface definition. This is done automaticalrly by Netbeans 7.3.
    3. Add business methods to AccountBeanRemote interface in the AccountCommon project.
    4. Implement those methods in the AccountBean class in AccountEJB project.
Project: AccountCommon
import javax.ejb.Remote;

/**
 * This is the Account remote interface.
 * 
 * @author rwatsh
 */
@Remote
public interface AccountBeanRemote {
    public double deposit(double amount);
    public double withdraw (double amount);
}

Project: AccountEJB
import javax.ejb.Stateful;

/**
 *
 * @author rwatsh
 */
@Stateful(name="AccountBean", mappedName="ejb/AccountBean")
public class AccountBean implements AccountBeanRemote {
    private double balance;
    
    @Override
    public double deposit(double amount) {
        balance += amount;
        return balance;
    }

    @Override
    public double withdraw(double amount) {
        balance -= amount;
        return balance;
    }
}


  1. Deploy the AccountEJB-ejb.jar to Glassfish v3 application server.
  2. Create an AccountClient Java EE application client which either looks up the AccoutBeanRemote interface using JNDI or has the container inject it at runtime using annotation @EJB. Invoke the business methods on the AccountBean.
Project: AccountClient
import com.rwatsh.ejb.AccountBeanRemote;
import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 *
 * @author rwatsh
 */
public class Main {

    //@EJB 
    //private static AccountBeanRemote acc;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws NamingException {
        double balance;
        Context c = new InitialContext();
        AccountBeanRemote acc = (AccountBeanRemote)c.lookup("ejb/AccountBean");
        balance = acc.deposit(1000);
        System.out.println(balance);
        balance = acc.deposit(2000);
        System.out.println(balance);
        balance = acc.withdraw(500);
        System.out.println(balance);
    }
}



Sunday, March 10, 2013

A Quick VBScript Tutorial


Option explicit
 Dim x, i

 i = 10

 x="Hello World"
 Wscript.Echo x

 'subroutine cannot return value like function returning void
 mysub()

 ' calling function which returns date
 Wscript.Echo myfunc()


 ' if then elseif else
 if i=10 then
 Msgbox("hello")
 i = i+1
 elseif i = 12 then
 Msgbox ("i is 12")

 else
 Msgbox("came to else")

 end if

' select case
Select case i
 case 11
Msgbox "i is 11"
case 20
Msgbox "i is 20"
case else
Msgbox "default case"
End Select

' for loop
For i= 0 To 5 step 1
Wscript.Echo "hello for loop"
Next

 'Msgbox x

 ' subroutine
 sub mysub()
Wscript.echo "This is mysub()"
 end sub

 ' function which returns date
 function myfunc()
myfunc= Date()
 end function

Thursday, March 07, 2013

Java 7 Locale Changes impacting Double.parseDouble() for some European Locales

Details on the Java 7 Locale related changes and its impact is captured succinctly at: http://blog.ej-technologies.com/2011/12/default-locale-changes-in-java-7.html 

 

A fix for the old code using Double.parseDouble() method which used to work fine with European locales like French (fr) and German (de) are broken since the parseDouble() method considers the value being passed to it to be in English format whereas a decimal value in French/German is represented with a comma and not a dot thus leading to a NumberFormatException. Prior to Java 7, the behavior for parseDouble() method was to expect the value to be in the current locale and not en_US.

A fix to the above issue is:

Locale loc = Locale.getDefault(Locale.Category.FORMAT); // get current locale
NumberFormat nf = NumberFormat.getNumberInstance(loc); // get number format for current locale
DecimalFormat df = (DecimalFormat)nf;
df.applyPattern(“#.##”); 
 
//Then replace occurrence of Double.parseDouble(df.format(c)) with the following:
 
Number number = nf.parse(df.format(c)); // parse the decimal string for current locale
System.out.println("Formt using NumberFormat "+ number.doubleValue());



According to Oracle, this is not a bug but a feature enhancement - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073906 


The enhancement was done to have the flexibility to write multi-lingual applications (applications showing data in more than one locale). Earlier entire application would default to just one selected locale.

Tuesday, March 05, 2013

Linux Mint 14 XFCE notebook


I got a Toshiba Satellite C855-S5194 notebook in a deal recently and installed Linux Mint 14 with Cinnamon and XFCE desktop.

This notebook came very cheap (for $330) and has Intel i3 processor which is dual core 2.5 GHz clock speed and has 6GB RAM (expandable upto 16GB), 650GB HDD and other usual stuff. I initially started with Cinnamon for my desktop but soon discovered that it was too heavy weight for my modest notebook so i installed Xubuntu desktop and noted that there was a significant performance improvement (CPU remains < 10%) with several applications like the email client, the browser with several tabs, the terminal sessions and the Eclipse IDE running simultaneously.

For more details on this notebook see:
http://us.toshiba.com/computers/laptops/satellite/C850/C855-S5194/

The build quality is pretty average (so handle with some gentleness :)) but i am amazed at the performance of the i3 processor which has hyper-threading support and so it shows up with 4 CPU threads in the system monitor.

In short, if you are looking for a Linux notebook which mostly sits like desktop but nevertheless gives some portability and performs well and comes at a low cost then this Toshiba notebook is a very decent option.

I did not keep Windows 8 (which this notebook came with pre-installed) for long so cannot comment on how well it performed but for the short while that i did have it, it seemed to be working smoothly, before it got erased by ubuntu first and then by linux mint eventually (after i figured out how to work around the secure boot and UEFI BIOS mode which did not let linux mint to boot from DVD).

By default the notebook had secure BIOS enabled and Boot mode set to UEFI. This will not let the Linux mint 14 to boot from DVD even after specifying DVD first in the boot order. Ubuntu does not have this limitation as its OS image is UEFI compatible and hence there was no issue in booting from an Ubuntu DVD. But for Linux Mint i needed to:

  1. Disable "Secure BIOS".
  2. Change Boot Mode from "UEFI boot" to "CSM boot".
After this it goes to legacy boot mode and booting from Linux Mint DVD will work fine and then you can proceed with installation.

Wednesday, January 23, 2013

Book Review: The Pragmatic Programmer: From Journeyman to Master

This is a nice book on the now common-place wisdom of programming or software engineering discipline. As a software engineer for 13 years I found it not so useful but nevertheless good in reviewing what are today well understood and common practices in the industry like the DRY principle (Don’t repeat yourself), Fix the broken windows today, refactoring etc. I highlighted some points as I was reading this book and I am reproducing them below (more for myself to be able to review these once in a while):

  1. Every day, work to refine the skills you have and to add new tools to your repertoire.
  2. The greatest of all weaknesses is the fear of appearing weak. • J. B. Bossuet, Politics from Holy Writ, 1709
  3. Don't leave "broken windows" (bad designs, wrong decisions, or poor code) unrepaired. Fix each one as soon as it is discovered.
  4. People find it easier to join an ongoing success. Show them a glimpse of the future and you'll get them to rally around.
  5. It's often the accumulation of small things that breaks morale and teams.
  6. Striving to better, oft we mar what's well. • King Lear 1.4
  7. As Ed Yourdon described in an article in IEEE Software [You95], you can discipline yourself to write software that's good enough—good enough for your users, for future maintainers, for your own peace of mind. You'll find that you are more productive and your users are happier. And you may well find that your programs are actually better for their shorter incubation.
  8. We are simply advocating that users be given an opportunity to participate in the process of deciding when what you've produced is good enough.
  9. Great software today is often preferable to perfect software tomorrow. If you give your users something to play with early, their feedback will often lead you to a better eventual solution.
  10. Don't spoil a perfectly good program by over-embellishment and over-refinement. Move on, and let your code stand in its own right for a while. It may not be perfect. Don't worry: it could never be perfect.
  11. An investment in knowledge always pays the best interest. • Benjamin Franklin
  12. Learn at least one new language every year.
  13. Read a technical book each quarter.
  14. Once you're in the habit, read a book a month.
  15. After you've mastered the technologies you're currently using, branch out and study some that don't relate to your project.
  16. Read nontechnical books, too.
  17. Take classes.
  18. Participate in local user groups.
  19. Start learning a new language this week.
  20. Start reading a new book
  21. Get out and talk technology with people who aren't involved in your current project, or who don't work for the same company. Network in your company cafeteria, or maybe seek out fellow enthusiasts at a local user's group meeting.
  22. I believe that it is better to be looked over than it is to be overlooked.
  23. You're communicating only if you're conveying information.
  24. Encourage people to talk by asking questions, or have them summarize what you tell them.
  25. Always respond to e-mails and voice mails, even if the response is simply "I'll get back to you later." Keeping people informed makes them far more forgiving of the occasional slip, and makes them feel that you haven't forgotten them.
  26. Where possible, always use accessor functions to read and write the attributes of objects.
  27. Two or more things are orthogonal if changes in one do not affect any of the others.
  28. Our preference is to start by separating infrastructure from application. Each major infrastructure component (database, communications interface, middleware layer, and so on) gets its own subteam. Each obvious division of application functionality is similarly divided. Then we look at the people we have (or plan to have) and adjust the groupings accordingly.
  29. There is an easy test for orthogonal design. Once you have your components mapped out, ask yourself: If I dramatically change the requirements behind a particular function, how many modules are affected? In an orthogonal system, the answer should be "one."
  30. Prototyping generates disposable code. Tracer code is lean but complete, and forms part of the skeleton of the final system.
  31. Prototyping is a learning experience. Its value lies not in the code produced, but in the lessons learned
  32. We think it's a great idea to record your estimates so you can see how close you were.
  33. Iterate the Schedule with the Code
  34. To ensure that we never lose any of our precious work, we should always use a Source Code Control system—even for things such as our personal address book!
  35. you can't be a great programmer until you become highly skilled at Debugging.
  36. Keep Knowledge in Plain Text
  37. Clearly the list could go on. The shell commands may be obscure or terse, but they are powerful and concise. And, because shell commands can be combined into script files (or command files under Windows systems), you can build sequences of commands to automate things you do often. Tip 21 Use the Power of Command Shells.
  38. Ideally, the shell you use should have keybindings that match the ones used by your editor. Bash, for instance, supports both vi and emacs keybindings.
  39. Choose an editor, know it thoroughly, and use it for all editing tasks.
  40. As one of the new languages you are going to learn this year, learn the language your editor uses. For anything you find yourself doing repeatedly, develop a set of macros (or equivalent) to handle.
  41. Try to accomplish any given editing task in as few keystrokes as possible.
  42. Progress, far from consisting in change, depends on retentiveness. Those who cannot remember the past are condemned to repeat it. • George Santayana, Life of Reason
  43. sounds simple, but in explaining the problem to another person you must explicitly state things that you may take for granted when going through the code
  44. Debugging Checklist -
    1. Is the problem being reported a direct result of the underlying bug, or merely a symptom?
    2. Is the bug really in the compiler?
    3. Is it in the OS? Or is it in your code?
    4. If you explained this problem in detail to a coworker, what would you say?
    5. If the suspect code passes its unit tests, are the tests complete enough?
    6. What happens if you run the unit test with this data?
    7. Do the conditions that caused this bug exist anywhere else in the system?
  45. Learn a Text Manipulation Language like perl.
  46. Good fences make good neighbors. • Robert Frost, "Mending Wall"
  47. Organize your code into cells (modules) and limit the interaction between them. If one module then gets compromised and has to be replaced, the other modules should be able to carry on.
  48. Traversing relationships between objects directly can quickly lead to a combinatorial explosion[1] of dependency relationships.
  49. We want to configure and drive the application via metadata as much as possible. Our goal is to think declaratively
  50. We need to allow for concurrency[3] and to think about decoupling any time or order dependencies. In doing so, we can gain flexibility and reduce any time-based dependencies in many areas of development: workflow analysis, architecture, design, and deployment.
  51. All functions related to the fulfillment of business logic fall into the category of core concerns.
  52. You can support multiple views of the same data model. You can use common viewers on many different data models. You can even support multiple controllers to provide nontraditional input mechanisms.
  53. Model. The abstract data model representing the target object. The model has no direct knowledge of any views or controllers. View. A way to interpret the model. It subscribes to changes in the model and logical events from the controller. Controller. A way to control the view and provide the model with new data. It publishes events to both the model and the view. Let's look at a nongraphical
  54. Each model may have many viewers, and one viewer may work with multiple models.
  55. Use Blackboards to Coordinate Workflow
  56. Network monitoring tool. The system gathers performance statistics and collects trouble reports. You'd like to implement some agents to use this information to look for trouble in the system.
  57. Sometimes we come up with fairly complex O() functions, but because the highest-order term will dominate the value as n increases, the convention is to remove all low-order terms, and not to bother showing any constant multiplying factors. O(n2/2+ 3n) is the same as O(n2/2), which is equivalent to O(n2).
  58. Rewriting, reworking, and re-architecting code is collectively known as refactoring.
  59. Workflow can be captured with UML activity diagrams, and conceptual-level class diagrams can sometimes be useful for modeling the business at hand.
  60. Teams as a whole should not tolerate broken windows—those small imperfections that no one fixes. The team must take responsibility for the quality of the product, supporting developers who understand the no broken windows philosophy.
  61. Make sure everyone actively monitors the environment for changes. Maybe appoint a chief water tester. Have this person check constantly for increased scope, decreased time scales, additional features, new environments—anything that wasn't in the original agreement.
  62. Divide your people into small teams, each responsible for a particular functional aspect of the final system. Let the teams organize themselves internally, building on individual strengths as they can.
  63. The project needs at least two "heads"—one technical, the other administrative. The technical head sets the development philosophy and style, assigns responsibilities to teams, and arbitrates the inevitable "discussions" between people. The technical head also looks constantly at the big picture, trying to find any unnecessary commonality between teams that could reduce the orthogonality of the overall effort. The administrative head, or project manager, schedules the resources that the teams need, monitors and reports on progress, and helps decide priorities in terms of business needs.
  64. To ensure that things get automated, appoint one or more team members as tool builders to construct and deploy the tools that automate the project drudgery. Have them produce makefiles, shell scripts, editor templates, utility programs, and the like.
  65. Remember that teams are made up of individuals. Give each member the ability to shine in his or her own way. Give them just enough structure to support them and to ensure that the project delivers against its requirements.
  66. Civilization advances by extending the number of important operations we can perform without thinking. • Alfred North Whitehead

Book Review: MY INVENTIONS: The Autobiography of Nikola Tesla

This book by Nikola Tesla is a quick read and does not go very detailed into his inventions like some biographies on Tesla do. It still has some lessons that Tesla conveys throughout the book on what he thought was different than normal in him and a one very unique thing that he says towards the end of the book is – when someone does bad to him then almost always he finds that person starts to pay for his deeds and he thought as if there is a mental influence one can have on others lives which he experienced but could not prove it to others but was very convinced that it was his mind that was causing his tormentor sufferings. Following are some things I remember:

  1. At one point Tesla says: When natural inclination develops into a passionate desire, one advances towards his goal in seven-league boots.
  2. He had been through near death experiences several times in his life.
  3. He had very sharp hearing capacity – but because of this he was not able to bear even sounds which may appear normal for most people.
  4. He was very inspired by reading works of Mark Twain once when he was very sick and bed-ridden. When he came to America and happened to befriend Mr Clemens himself who Tesla describes to be a man of very jovial nature and tells the author that his books were the reason he could recover from his sickness as they gave him the strength to live then at hearing this Mark Twain (Mr Clemens) started to cry like a child and said it was the greatest reward for him.
  5. Of note, Tesla does not say anything about Edison (or not that I remember now so even if he did it was only done in the passing).

A good quick read and an inspiring one at that. Highly recommended.