Java8 lambda expression variable

public class TrickyLambdaExpressionDemo {
public static void main(String …args){
String name = “Hello World”;
Runnable r1 = ()-> System.out.println(name);

String name1 = “”;
name1 = name.toUpperCase();
Runnable r2 = ()-> System.out.println(name1);

r1.run();
}
}

What will be the result, if you run the above code?

The answer is “Compile Error”. The error is “Variable used in Lambda expression must be effectively final”.

If you change it to

String name1 = name.toUpperCase();

Then it will print out “Hello World”

Another point we should pay attention to is the word “effectively final” what is the difference between final and effectively final?

I always think lambda expression is a kind of anonymous class. In Java any local variable within an anonymous class should be final! Thus it is reasonable lambda expression requires variable to be final. But why effectively final? it means although the developer does not put the keyword final in front of the variable, in the above sample it is name1, if once it has been initialised,  the value never changed, the variable can be treated as final. This saves developer a lot of time to avoiding put the keyword final in front of any lambda variables.

Couchbase document can be found in console but cant be found in program

Q: Couchbase document can be found in console but can’t be found in program. In console if you run the following command it will find the required document. It is working totally in the sqi env.

curl http://:8093/query/service -d ‘statement=select * from `uat` where any myorder IN orders SATISFIES myorder.id=”12345678″ END &creds=[{“user”:,”pass”:””}]’

However in the application the same statement is executed, it returns 0 result. The code looks like this:

public ServiceInventory getServiceInventoryByOrderId(final String orderId) throws ServiceInventoryException {
final String PLACEHOLDER_STATEMENT =
“select * from `” + this.bucketName + “` USE INDEX(orderid_idx) where any myorder IN orders SATISFIES myorder.id = ‘” + orderId +”‘ END”;
log.debug(“The statement we are going to execute is {}”, PLACEHOLDER_STATEMENT);

final N1qlQueryResult result = this.executeN1qlQuery(N1qlQuery.simple(PLACEHOLDER_STATEMENT));
log.info(“The size of the query result is {}”, result.allRows().size());
final List serviceInventoryList = result.allRows().stream().map(n1qlQueryRow -> {
final JsonObject document = (JsonObject) n1qlQueryRow.value().get(this.bucketName);
if (document == null) {
log.info(“Can not find anything based on {}”, this.bucketName);
}
return gsonObj.fromJson(document.toString(), ServiceInventory.class);
}).collect(Collectors.toList());

if (CollectionUtils.isEmpty(serviceInventoryList)) {
throw new ServiceInventoryException(
“Can not find a matched Service Inventory Object by orderId = ” + orderId);
}

return serviceInventoryList.get(0);

}

A:Why it is so weird? Why it is working ONLY in console?

In the method executeN1qlQuery(…) log.debug(“bucket.query time = [{}] “, System.currentTimeMillis() – startTime); can be executed, it got stuck in bucket.query(query). So what is the connection string in the bucket?
There is an assumption here, the connection String in the code is the same as the command I ran in console. But is it really the same? No. If you replace stl-nbn-cb45e-uat-cl001.np.stl.np.top.corp.telstra.com with the connection string I use in code, the execution of the command will be failed.

Postman call is successful but in code the same URL, the REST call is failed

Q: I was asked to write a REST call to a third party address service. Everything is fine but when we are trying to test it on code base level, it failed! The call to https:///v1/ failed. But it is successful in postman, how come? It is weird.

A: The service address call is a two-steps call, one is to get the token the second step is insert this token into headers and do a REST call. After investigating, I found the problem is in the headers. Below is the code:
private HttpHeaders getHttpHeaders(final String token, final String correlationId) {
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
return headers;
}
It seems like the downstream system does not like UTF8. So if you change it to:
private HttpHeaders getHttpHeaders(final String token, final String correlationId) {
final HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
return headers;
}
The problem is resolved.

My experience in pair programming

My previous company is very famous for its pair programming, below are my thoughts

pros:
  • more efficient;
  • in conjunction with TDD, less bug;
  • easier to setup (when you are new);
  • know the whole project;
  • easy to transfer knowledge from senior to new comer;
  • as a single developer it is very easy to miss some possibility/risk for a solution, but for pair programming your pair may help you.
cons:
  • if your pair is sick (or in absence), then you can’t do anything, especially when you are new.
  • less private. I do think, especially in programming, sometimes you need to concentrate, you need to work alone; Working alone sometimes can reach higher quality;
  • Feel pressure when sb is “monitoring” you. I am not lazy just feel uncomfortable or if you can’t fix a problem you will feel pressure
  • ow to do it when we outsource a lot to India?

Why always override hashcode() if overriding equals()?

This is one the most frequent questions I was asked in interview.

You can override the default implementation of the equals() method defined in java.lang.Object. If you override the equals(), you MUST also override hashCode(). Otherwise a violation of the general contract for Object.hashCode will occur, which can have unexpected repercussions when your class is in conjunction with all hash-based collections.

The default implementation of equals() method checks to see if the two objects have the same identity. Similarly, the default implementation of the hashCode() method returns an integer based on the object’s identity and is not based on the values of instance (and class) variables of the object. No matter how many times the values of its instance variables (data fields) change, the hash code calculated by the default hashCode implementation does not change during the life of the object.

Consider the following code, we have overridden equals() method to check if two objects are equal based on the values of their instance variables. Two objects may be stored at different memory addresses but may still be equal base on their instance variable.

public class CustomerID {
private long crmID;
private int nameSpace;

public CustomerID(long crmID, int nameSpace) {
super();
this.crmID = crmID;
this.nameSpace = nameSpace;
}

public boolean equals(Object obj) {
//null instanceof Object will always return false
if (!(obj instanceof CustomerID))
return false;
if (obj == this)
return true;
return this.crmID == ((CustomerID) obj).crmID &&
this.nameSpace == ((CustomerID) obj).nameSpace;
}

public static void main(String[] args) {
Map m = new HashMap();
m.put(new CustomerID(2345891234L,0),”Jeff Smith”);
System.out.println(m.get(new CustomerID(2345891234L,0)));
}

}

Compile and run the above code, the output result is

null
What is wrong? The two instances of CustomerID are logically equal according to the class’s equals method. Because the hashCode() method is not overridden, these two instances’ identities are not in common to the default hashCode implementation. Therefore, the Object.hashCode returns two seemingly random numbers instead of two equal numbers. Such behavior violates “Equal objects must have equal hash codes” rule defined in the hashCode contract.

Let’s provide a simple hashCode() method to fix this problem:

public class CustomerID {
private long crmID;
private int nameSpace;

public CustomerID(long crmID, int nameSpace) {
super();
this.crmID = crmID;
this.nameSpace = nameSpace;
}

public boolean equals(Object obj) {
//null instanceof Object will always return false
if (!(obj instanceof CustomerID))
return false;
if (obj == this)
return true;
return this.crmID == ((CustomerID) obj).crmID &&
this.nameSpace == ((CustomerID) obj).nameSpace;
}

public int hashCode() {
int result = 0;
result = (int)(crmID/12) + nameSpace;
return result;
}

public static void main(String[] args) {
Map m = new HashMap();
m.put(new CustomerID(2345891234L,0),”Jeff Smith”);
System.out.println(m.get(new CustomerID(2345891234L,0)));
}

}
Compile and run the above code, the output result is

Jeff Smith

Code Coverage Result is defferent when use Jacoco

Q: The code coverage for my microservice is always low, even for some classes the code coverage is 0%, how come? since when I run it locally it is 100% code coverage, it should not have such a big gap.
A: According to https://github.com/powermock/powermock/issues/422 it seems like Jacoco is not very friend with PowerMock. Unfortunately my test cases are using PowerMock (since I can test private method through Powermock)
After switch from Powermock to Mockito, my problem fixed.

How to generate SSH Key

An SSH key allows you to establish a secure connection between your computer and GitLab.
Before generating an SSH key, check if your system already has one by running
cat ~/.ssh/id_rsa.pub
If you see a long string starting with ssh-rsa or ssh-dsa, you can skip the ssh-keygen step.
To generate a new SSH key, just open your terminal and use code below. The ssh-keygen command prompts you for a location and filename to store the key pair and for a password. When prompted for the location and filename, you can press enter to use the default.
It is a best practice to use a password for an SSH key, but it is not required and you can skip creating a password by pressing enter. Note that the password you choose here can’t be altered or retrieved.
ssh-keygen -t rsa -C “username@gmail.com”
Use the code below to show your public key.
cat ~/.ssh/id_rsa.pub
Copy-paste the key to the ‘My SSH Keys’ section under the ‘SSH’ tab in your user profile. Please copy the complete key starting with ssh- and ending with your username and host.
Use code below to copy your public key to the clipboard. Depending on your OS you’ll need to use a different command:
Windows:
clip < ~/.ssh/id_rsa.pub
Mac:
pbcopy < ~/.ssh/id_rsa.pub
Linux (requires xclip):
xclip -sel clip < ~/.ssh/id_rsa.pub
Deploy keys allow read-only access to multiple projects with a single SSH key.
This is really useful for cloning repositories to your Continuous Integration (CI) server. By using deploy keys, you don’t have to setup a dummy user account.
If you are a project master or owner, you can add a deploy key in the project settings under the section ‘Deploy Keys’. Press the ‘New Deploy Key’ button and upload a public SSH key. After this, the machine that uses the corresponding private key has read-only access to the project.
You can’t add the same deploy key twice with the ‘New Deploy Key’ option. If you want to add the same key to another project, please enable it in the list that says ‘Deploy keys from projects available to you’. All the deploy keys of all the projects you have access to are available. This project access can happen through being a direct member of the projecti, or through a group. See def accessible_deploy_keys in app/models/user.rb for more information.

Annoying .idea files are commited into repository

IntelliJ is a good developing tool but it will generate a folder called .idea, which contains all your local settings. It is NOT supposed to be pushed to repository. So you need to ignore them by editing your .gitignorre file. Please be noted this is a hidden file, you can do the below within your Git Bash.
(The below not only can be applied to .idea but .setting and .iml files)http://stackoverflow.com/questions/11968531/what-to-gitignore-from-the-idea-folder
vi .gitignore
/target
.idea
*.iml
.classpath
.project
.settings
*.checkstyle
If unfortunately you have already committed those changes do the followings:
$ echo ‘.idea’ >> .gitignore
$ git rm -r –cached .idea
$ git add .gitignore
$ git commit -m ‘(some message stating you added .idea to ignored entries)’
$ git push

Rabbit MQ Server Crash on badmatch

I installed rabbitMQ locally. All of a sudden it stopped working and started to complain badmatch error as follows, since my voice-dm highly depend on it (it seems to me the application keeps trying to connect to rabbitMQ), I’ve tried to terminate the rabbitMQ process in task manager and restart it by using command line “rabbitmq-server.bat start” but the error persist.

=CRASH REPORT==== 11-Jan-2017::08:27:03 ===
crasher:
initial call: application_master:init/4
pid: <0.162.0>
registered_name: []
exception exit: {bad_return,
{{rabbit,start,[normal,[]]},
{‘EXIT’,
{{badmatch,
{error,
{{{badmatch,
{error,
{not_a_dets_file,
“c:/Users/d639174/AppData/Roaming/RabbitMQ/db/RABBIT~3/recovery.dets”}}},
[{rabbit_recovery_terms,open_table,0,
[{file,”src/rabbit_recovery_terms.erl”},
{line,130}]},
{rabbit_recovery_terms,init,1,
[{file,”src/rabbit_recovery_terms.erl”},
{line,111}]},
{gen_server,init_it,6,
[{file,”gen_server.erl”},{line,304}]},
{proc_lib,init_p_do_apply,3,
[{file,”proc_lib.erl”},{line,239}]}]},
{child,undefined,rabbit_recovery_terms,
{rabbit_recovery_terms,start_link,[]},
transient,4294967295,worker,
[rabbit_recovery_terms]}}}},
[{rabbit_queue_index,start,1,
[{file,”src/rabbit_queue_index.erl”},{line,468}]},
{rabbit_variable_queue,start,1,
[{file,”src/rabbit_variable_queue.erl”},{line,439}]},
{rabbit_priority_queue,start,1,
[{file,”src/rabbit_priority_queue.erl”},{line,92}]},
{rabbit_amqqueue,recover,0,
[{file,”src/rabbit_amqqueue.erl”},{line,236}]},
{rabbit,recover,0,
[{file,”src/rabbit.erl”},{line,654}]},
{rabbit_boot_steps,’-run_step/2-lc$^1/1-1-‘,1,
[{file,”src/rabbit_boot_steps.erl”},{line,49}]},
{rabbit_boot_steps,run_step,2,
[{file,”src/rabbit_boot_steps.erl”},{line,49}]},
{rabbit_boot_steps,’-run_boot_steps/1-lc$^0/1-0-‘,1,
[{file,”src/rabbit_boot_steps.erl”},{line,26}]}]}}}}
in function application_master:init/4 (application_master.erl, line 133)
ancestors: [<0.161.0>]

After reading the logs under C:\Users\d639174\AppData\Roaming\RabbitMQ\log (this is described in the command line)

screen-shot-2017-01-29-at-3-20-35-pm

I think it is complaining there is something wrong with the recovery.dets file as shown in follows:

Screen Shot 2017-01-29 at 3.22.12 pm.png

I opened the location of this file and renamed it to recovery.dets_del
Then restart the service by running the command line “rabbitmq-server.bat start” the problem has been fixed and a new recovery.dets file is created