Go Reactive - RxJava Example

The following code shows how to use RxJava Observable to create service , and how to call it asynchronously and synchronously in client side.
    public static void main(final String[] args) throws InterruptedException {
        Observable<Void> observable = createAsycService();
        asyncObservableClient(observable);

        observable = createAsycService();
        syncObservableClient(observable);

        LOGGER.info("main-wait for some time");
        Thread.sleep(1000 * 10);
        LOGGER.info("main-finished");
    }

    private static Observable<Void> createAsycService() {
        final Observable<Void> observable = Observable.<Void>create(new OnSubscribe<Void>() {
            @Override
            public void call(final Subscriber<? super Void> subscriber) {
                LOGGER.info("service-started");
                try {
                    Thread.sleep(1000 * 2);
                } catch (final InterruptedException e) {
                    e.printStackTrace();
                }
                LOGGER.info("service-finished");
                // we should always call onNext(), so sync client can handle it easily.
                subscriber.onNext(null);
                // tell observer we are done
                subscriber.onCompleted();
            }
        }).subscribeOn(Schedulers.newThread());
        return observable;
    }

    private static void syncObservableClient(final Observable<Void> observable) {
        LOGGER.info("sync-client-started");

        final BlockingObservable<Void> blockingObservable = observable.timeout(5, TimeUnit.SECONDS).toBlocking();
        blockingObservable.last();
        LOGGER.info("sync-client-finished");
    }

    private static void asyncObservableClient(final Observable<Void> observable) {
        observable.subscribe(new Subscriber<Void>() {
            @Override
            public void onCompleted() {
                LOGGER.info("async-client-finished");
            }

            @Override
            public void onError(final Throwable e) {
                LOGGER.info("async-client:" + e.getMessage());
            }

            @Override
            public void onNext(final Void t) {
                LOGGER.info("async-client-received:" + t);
            }
        });
    }
Resources:

Lazy Developer: Using git pre-commit to auto tun test and findbugs

The Goal:
We developers wish our code is perfect, no bug, and we never want to check in code that will break test and found out later by peers.


We should always use tools like findbugs to check our code and run test locally before we push the change to git repository.

But would be better if git could just run test, check bugs for us before commit or push?

Using git pre-commit to run mvn test automatically
Luckily we can use git pre-commit hooks to do this for us.
We just need create pre-commit file in .git/hooks folder, make it executable(chmod 755), In this script, we can do anything we want.

In the following script, it will check whether we changed java code or pom file in this commit, if no, just commit it(we don't have test for UI side yet).

If yes, it will first stash(save and hide) unstaged changes before running tests, so we are really testing code that will be committed. 
#!/bin/bash
# At root folder project: run ln -s ../../utils/git/pre-commit .git/hooks/pre-commit
echo "running pre-commit hooks"

STAGED_FILES_CMD=`git diff --cached --name-only | grep -E "(\.java$)|(pom.xml)"`
# Determine if a file list is passed
ECHO "INPUT: $#"
if [ "$#" -eq 1 ]
then
 oIFS=$IFS
 IFS='
 '
 SFILES="$1"
 IFS=$oIFS
fi
SFILES=${SFILES:-$STAGED_FILES_CMD}

echo "STAGED_FILES_CMD: $STAGED_FILES_CMD, SFILES: $SFILES"
# Determine whether need run maven java test
if [ "$SFILES" == "" ]
then
 echo "no need to run maven test";
 exit 0;
fi

echo "Running maven clean test for errors"

# Stash changes
git stash -q --keep-index

# retrieving current working directory, if don't want to call this hook, run git commit --no-verify
CWD=`pwd`
MAIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# go to main project dir
cd $MAIN_DIR/../../
mkdir logs/

set -o pipefail
/usr/local/bin/mvn clean test package | tee logs/mvn.log

RESULT=$?
# Restore changes
git stash pop -q

if [ $RESULT -ne 0 ]; then
  echo "Error while testing the code"
  # in case when we run it in eclipse.
  open logs/mvn.log
  # go back to current working dir
  cd $CWD
  exit 1
fi
# go back to current working dir
cd $CWD
Add pre-commit hooks into git
Each developer should run ln -s ../../tools/git/pre-commit .git/hooks/pre-commit
So if we make any change, others can just pick the change.

Run findbugs during compile, fail build if find bugs
Add findbugs to pom:
<plugin>
 <groupId>org.codehaus.mojo</groupId>
 <artifactId>findbugs-maven-plugin</artifactId>
 <version>${org.codehaus.mojo.version}</version>
 <configuration>
  <effort>Max</effort>
  <threshold>Medium</threshold>
  <xmlOutput>true</xmlOutput>
  <failOnError>true</failOnError>
 </configuration>
 <executions>
  <!-- Ensures that FindBugs inspects source code when project is compiled. -->
  <execution>
   <id>analyze-compile</id>
   <phase>compile</phase>
   <goals>
    <goal>check</goal>
   </goals>
  </execution>
 </executions>
</plugin>

We also added Google Error Prone as a step of mvn compile
Resources:

JAX-RS: capture all error, don't expose internal stack trace

The Goal: Don't expose internal stack trace to client

Capture all Error
When we are developing restful API that are exposed to the internet,  we better capture all exception/error, and don't expose internal stack trace to outside.

In Jersey, we can use ExceptionMapper to capture any kind of exception or error.
For known exception such as ProductNotFound, we can capture it, and return meaningful error message to client.

But bad things always happen, our application may throw NullPointerExceptionn or exception that we don't ever expect or may throw OutOfMemoryError.

When this happens, we need capture it, return some message like: "internal error", and then asynchronously notify engineer owners(send email, store to db or or other approaches).

public class GenericExceptionMapper implements ExceptionMapper {
    private static final Logger LOGGER = LoggerFactory.getLogger(GenericExceptionMapper.class);
    private static final String MSG_INTERNAL_ERROR = "internal error.";
    public static final String HEADER_ERROR_CODE = "X-ErrorCode";

    @Override
    public Response toResponse(Throwable exception) {
        // including exception's type and message in the log message to facilitate log navigation

        // here we capture all error, so no stack trace is exposed to client.
        // TODO alert developers
        LOGGER.error("Unhanded exception detected {}:{}",
                new Object[] {exception.getClass(), exception.getMessage(), exception});

        if (exception instanceof OutOfMemoryError) {
            // notify engineer owner
        } else {
            // may caused by program bug
            // store the error to separate log or db, so we can check them easily
        }

        ResponseBuilder builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR);
        builder.header(HEADER_ERROR_CODE, MSG_INTERNAL_ERROR);
        builder.entity(new ErrorMessage(MSG_INTERNAL_ERROR)).type(MediaType.APPLICATION_JSON);
        return builder.build();
    }
}

Code is the King
How Jersey find exception mapper for specific exception?
com.sun.jersey.spi.container.ContainerResponse.mapException(Throwable)
com.sun.jersey.server.impl.application.ExceptionMapperFactory.find(Class)

It checks all exception mappers, get the exception mapper whose exception type is isAssignableFrom and the distance from current exception is smallest.

If can't find. it will ResponseListener onError, which by default returns html page with error stack trace.

    public ExceptionMapper find(Class c) {
        int distance = Integer.MAX_VALUE;
        ExceptionMapper selectedEm = null;
        for (ExceptionMapperType emt : emts) {
            int d = distance(c, emt.c);
            if (d < distance) { 
                distance = d;
                selectedEm = emt.em;
                if (distance == 0) break;
            }
        }
        
        return selectedEm;
    }
    
    private int distance(Class c, Class emtc) {
        int distance = 0;
        if (!emtc.isAssignableFrom(c))
            return Integer.MAX_VALUE;
        
        while (c != emtc) {
            c = c.getSuperclass();
            distance++;
        }
        
        return distance;
    }

Labels

Java (159) Lucene-Solr (110) Interview (61) All (58) J2SE (53) Algorithm (45) Soft Skills (37) Eclipse (33) Code Example (31) Linux (24) JavaScript (23) Spring (22) Windows (22) Web Development (20) Nutch2 (18) Tools (18) Bugs (17) Debug (16) Defects (14) Text Mining (14) J2EE (13) Network (13) Troubleshooting (13) PowerShell (11) Chrome (9) Design (9) How to (9) Learning code (9) Performance (9) Problem Solving (9) UIMA (9) html (9) Http Client (8) Maven (8) Security (8) bat (8) blogger (8) Big Data (7) Continuous Integration (7) Google (7) Guava (7) JSON (7) ANT (6) Coding Skills (6) Database (6) Scala (6) Shell (6) css (6) Algorithm Series (5) Cache (5) Dynamic Languages (5) IDE (5) Lesson Learned (5) Programmer Skills (5) System Design (5) Tips (5) adsense (5) xml (5) AIX (4) Code Quality (4) GAE (4) Git (4) Good Programming Practices (4) Jackson (4) Memory Usage (4) Miscs (4) OpenNLP (4) Project Managment (4) Spark (4) Testing (4) ads (4) regular-expression (4) Android (3) Apache Spark (3) Become a Better You (3) Concurrency (3) Eclipse RCP (3) English (3) Happy Hacking (3) IBM (3) J2SE Knowledge Series (3) JAX-RS (3) Jetty (3) Restful Web Service (3) Script (3) regex (3) seo (3) .Net (2) Android Studio (2) Apache (2) Apache Procrun (2) Architecture (2) Batch (2) Bit Operation (2) Build (2) Building Scalable Web Sites (2) C# (2) C/C++ (2) CSV (2) Career (2) Cassandra (2) Distributed (2) Fiddler (2) Firefox (2) Google Drive (2) Gson (2) How to Interview (2) Html Parser (2) Http (2) Image Tools (2) JQuery (2) Jersey (2) LDAP (2) Life (2) Logging (2) Python (2) Software Issues (2) Storage (2) Text Search (2) xml parser (2) AOP (1) Application Design (1) AspectJ (1) Chrome DevTools (1) Cloud (1) Codility (1) Data Mining (1) Data Structure (1) ExceptionUtils (1) Exif (1) Feature Request (1) FindBugs (1) Greasemonkey (1) HTML5 (1) Httpd (1) I18N (1) IBM Java Thread Dump Analyzer (1) JDK Source Code (1) JDK8 (1) JMX (1) Lazy Developer (1) Mac (1) Machine Learning (1) Mobile (1) My Plan for 2010 (1) Netbeans (1) Notes (1) Operating System (1) Perl (1) Problems (1) Product Architecture (1) Programming Life (1) Quality (1) Redhat (1) Redis (1) Review (1) RxJava (1) Solutions logs (1) Team Management (1) Thread Dump Analyzer (1) Visualization (1) boilerpipe (1) htm (1) ongoing (1) procrun (1) rss (1)

Popular Posts