Why Angular 2

Early this year, I began on a self-righteous (but approved, of course ūüėČ )¬†journey to make things right¬†for my project —¬†to break all shackles and limitations that the¬†team faces in working with older technologies, methodologies and guidelines. When I started off, my aim was¬†to make as minimal-but-essential changes to the system as possible, keeping in mind that¬†my¬†project is a live one, having at least 100 MegaBytes¬†of code, with around 16¬†developers contributed¬†to this application¬†—¬†in batches, of course¬†—¬†in¬†the past 8 years, each having their own signature style of coding.¬†Needless to say, there were more than a few tasks for research in this journey of mine.

One such, important analysis was to decide what UI methodology should the team adopt going forward. This blog post will focus on the analyses and decision-making process that made it happen and finally helped me decide on Angular 2.

Continue reading

Build a Custom Solr Filter to Handle Unit Conversions

Recently, I came across a use case where it was required to handle units of weight in the index. For instance, 2kg and 2000g, when searched should return the same set of results.

So, for achieving the above, I wrote a custom Solr filter that will work along with KeywordTokenizer to convert all units of weight in the incoming request to a single unit (g) and hence every measurement will be saved in the form of a number; at the same time, it will also keep units like kg/g/mg intact while returning the docs.

Firstly, we need to write custom tokenfilter and tokenfilterfactory .

UnitConversionFilter.java


package com.solr.custom.filter.test;
import java.io.IOException;

import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;

/**
 * @author SumeetS
 *
 */
public class UnitConversionFilter extends TokenFilter{

private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);

/**
 * @param input
 */
 public UnitConversionFilter(TokenStream input) {
 super(input);
 }

/* (non-Javadoc)
 * @see org.apache.lucene.analysis.TokenStream#incrementToken()
 */
 @Override
 public boolean incrementToken() throws IOException {
 if (input.incrementToken()) {
// charUtils.toLowerCase(termAtt.buffer(), 0, termAtt.length());
 int length = termAtt.length();
 String inputWt = termAtt.toString(); //assuming format to be 1kg/mg
 float valInGrams = convertUnit(inputWt);
 String storeFormat = valInGrams+"";
 termAtt.setEmpty();
 termAtt.copyBuffer(storeFormat.toCharArray(), 0, storeFormat.length());
 return true;
 } else
 return false;
 }

 private float convertUnit(String field){
 String [] tmp = field.split("(k|m)?g");
 float weight = Integer.parseInt(tmp[0]);
 String[] tmp2 = field.split(tmp[0]);
 String unit = tmp2[1];
 float convWt = 0;
 switch(unit) {
 case "kg":
 convWt = weight * 1000;
 break;
 case "mg":
 convWt = weight /1000;
 break;
 case "g":
 convWt = weight;
 break;
 }
 return convWt;
 }
}

UnitConversionTokenFilterFactory.java


package com.solr.custom.filter.test;
import java.util.Map;

import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.util.TokenFilterFactory;

/**
 * @author SumeetS
 *
 */
public class UnitConversionTokenFilterFactory extends TokenFilterFactory {

/**
 * @param args
 */
 public UnitConversionTokenFilterFactory(Map<String, String> args) {
 super(args);
 if (!args.isEmpty()) {
 throw new IllegalArgumentException("Unknown parameters: " + args);
 }
 }

/* (non-Javadoc)
 * @see org.apache.lucene.analysis.util.TokenFilterFactory#create(org.apache.lucene.analysis.TokenStream)
 */
 @Override
 public TokenStream create(TokenStream input) {
 return new UnitConversionFilter(input);
 }

}

NOTE: When you override the TokenFilter and TokenFilterFactory, make sure to edit the protected constructors to public, otherwise it will throw NoSuchMethodException during plugin init.

Now, compile and export your above classes into a jar say customUnitConversionFilterFactory.jar

Steps to Deploy Your Jar Into Solr

1. Place your jar file under /lib

2. Make an entry in solrConfig.xml file to help it identify your custom jar.


	<lib dir="../../../lib/" regex=".*\.jar" />

3. Add custom fieldType and field in your schema.xml

 

<field name="unitConversion" type="unitConversion" indexed="true" stored="true"/>
<fieldType name="unitConversion" class="solr.TextField" positionIncrementGap="100">
<analyzer>
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="com.solr.custom.filter.test.UnitConversionTokenFilterFactory" />
</analyzer>
</fieldType>

4. Now restart Solr and browse to the Solr console//documents

5. Add documents in your index like below:

{"id":"tmp1","unitConversion":"1000g"}
{"id":"tmp2","unitConversion":"2kg"}
{"id":"tmp3","unitConversion":"1kg"}

6. Query your index.

Query1 : querying for documents with 1kg

http://localhost:8983/solr/core1/select?q=*%3A*&fq=unitConversion%3A1kg&wt=json&indent=true

Result:

{
 "responseHeader":{
 "status":0,
 "QTime":0,
 "params":{
 "q":"*:*",
 "indent":"true",
 "fq":"unitConversion:1kg",
 "wt":"json"}},
 "response":{"numFound":2,"start":0,"docs":[
 {
 "id":"tmp1",
 "unitConversion":"1000g",
 "_version_":1524411029806645248},
 {
 "id":"tmp3",
 "unitConversion":"1kg",
 "_version_":1524411081738420224}]
 }}

Query2: querying for documents with 2kg

http://localhost:8983/solr/core1/select?q=*%3A*&fq=unitConversion%3A2kg&wt=json&indent=true

Result:

{
 "responseHeader":{
 "status":0,
 "QTime":0,
 "params":{
 "q":"*:*",
 "indent":"true",
 "fq":"unitConversion:2kg",
 "wt":"json"}},
 "response":{"numFound":1,"start":0,"docs":[
 {
 "id":"tmp2",
 "unitConversion":"2kg",
 "_version_":1524411089834475520}]
 }}

Query3: let’s try faceting

http://localhost:8983/solr/core1/select?q=*%3A*&rows=0&wt=json&indent=true&facet=true&facet.field=unitConversion

{
 "responseHeader":{
 "status":0,
 "QTime":1,
 "params":{
 "q":"*:*",
 "facet.field":"unitConversion",
 "indent":"true",
 "rows":"0",
 "wt":"json",
 "facet":"true"}},
 "response":{"numFound":335,"start":0,"docs":[]
 },
 "facet_counts":{
 "facet_queries":{},
 "facet_fields":{
 "unitConversion":[
 "1000.0",2,
 "2000.0",1]},
 "facet_dates":{},
 "facet_ranges":{},
 "facet_intervals":{},
 "facet_heatmaps":{}}}

This is just a basic implementation. One can add additional fields to identify the type of unit and then based on that decide the conversion.

Further improvements include handling of range queries along with the units.

For more info check us out in Social Media, we were recently able to Buy Instagram likes to improve our account.

Edge Side Includes (ESI)

Traditionally web applications were meant to serve static content, wherein the server generated an HTML response to the client’s request (typically HTTP) and sent it back to the client. The response was then rendered on user’s screen (browser window) by the client (browser). In order to increase user-perceived performance, such static content was cached at the edge of Internet so that it could be served faster. Content Delivery Networks (CDNs) have been used commercially for such purposes.

Using Revealing Module Pattern with Web Interface Design

I recently joined a project that required me to develop a mobile website for the client. We already had a fully functional desktop version of the website. There were around 10000+ lines of JavaScript code for the existing desktop website and most of it was not at all reusable for the mobile website. The purpose of this blog post is to identify what went wrong with the original design of the JavaScript code and to provide a solution that could have saved around two to three weeks of (re)work.

 

The Problems

Following are some issues that made us re-implement the complete functionality from scratch. Later the approach and guidelines that we implemented to avoid the same problem again will be discussed.

JQuery (mis)usage
Many methods implementing some business logic were used $(‘#id‚Äô) to access values. To reuse this code, I‚Äôd have had to use exactly same id/classes for elements.

Too many document.ready()
Each script included on the page had its own document ready handler. Multiple entry points made it hard to determine the flow of code.

Modular approach
The whole JavaScript code was organized as global functions. Need I say more?

Code Repetition
At some places, very similar or even the same functionality was implemented in different functions. Validation and error handling code was also repeated at a number of places.

Repeated element ids

Same elements id were used at a number of places.

What Affects What?
It was hard to determine which piece of code was intended for which part of the page. Some JavaScript files were being used on multiple pages. There each page was broken into several jspx files that may or may not be included on the page depending on some business logic. Also, some of those jspx had conditions of their own to add or skip some elements.

The Required Solution

Now that we have looked at the major problems with the existing JavaScript code, let’s take each of the problems and see what we can do to avoid them.
JQuery (mis)usage
To fix this, we needed to separate the business logic from UI logic. E.g. code to update user information on server should not be defined in the click handler of the submit button. We should, instead, put the ajax call in a separate function, taking the user details as parameters. The click handler should gather user details from form elements and pass them to the function. Similarly, use callbacks to update UI when a response is received from the server.

In UI code, we should be able to somewhere define ids of various form fields instead of hard coding field ids everywhere.

Too many document.ready()  
There should be only one script with document ready handler, and it should be responsible to initialize various modules used on the page.
Modular approach & What affects what?
We needed an object oriented approach with business and UI logic in separate modules. Also, we needed some sort of mapping between the UI modules and jspx files. This would make it easier to determine exactly what code needs to be updated if something changes on the UI.
Code repetition
We needed to organize modules neatly. The business logic modules should have some sort of hierarchy based on functionality. The UI modules should maintain same hierarchy as the back end jspx files.
The validation and error handling code should be moved outside business and UI logic, in separate modules of their own.
Repeated element ids
It was simple to use unique ids in a single jspx file. However, on a completely rendered page we could still have repeated ids, especially when a jspx file was included more than once on a page. So, while inserting a jspx file, we also needed to wrap it inside a div container with unique id. We also needed some approach to be able to identify each element without specifying complete id-hierarchy.

Coding/Design Guidelines

To implement the changes suggested in the previous section, I had to write some utility modules to handle things such as validation, error handling, a JQuery wrapper to transparently access DOM elements with full id etc.

Following are some design and coding guidelines that I followed while implementing the mobile website.

Jspx Design Guidelines

  • Every id in a jspx file should be unique.
  • Every jspx file should be included inside a div container of its own; the container should be given a unique id in the jspx file.
  • All form fields should use a common markup style at all places e.g. each field should be placed inside a div container with proper classes such as ‘textbox’, ‘disabled’, ‘read-only’ etc

JavaScript coding guidelines

  • Organize the code in some meaningful namespaces, clearly separating business logic, UI logic and form validation and error handling code.
  • None of the code in business logic must interact with UI. Any of the business logic functions must accept required data and callback functions as arguments.
  • The business logic modules should be singletons unless it is required to create multiple objects of the module.
  • A UI module should be created for each jspx file.
  • For each jspx file included, a module must create objects of each of the module respective to included jspx files.
  • Any HTML element should be accessed only by its respective module.
  • While creating a child UI module, the parent module must pass the full id of its child jspx’s container div to the child module.
  • Define all form fields and HTML elements of the respective jspx accessed in the module.
  • While accessing any field by id in a UI module, the field id should be appended to the full id of the container div passed by the parent module. (We implemented a utility module to transparently handle this).
  • Define callbacks in each UI module for any event that might be interesting to the parent module.¬† e.g. submitButtonClicked, someCheckBoxChecked etc.
  • In case a child module needs to update parent module for some event, it must do so via callbacks. The parent module needs to set these callbacks at the time of creating the child module object.
  • Define public functions for actions requested by parent module. e.g. enableSubmitButton(), showSomeHiddenElement() etc.
  • In case a parent module needs to update UI for a child module, it must do via public functions exposed by the child module.
  • Don’t access HTML element attributes directly. For example, to hide elements don‚Äôt change display style. Create CSS classes for each required state of HTML elements and add/remove these classes to update any
  • Avoid creating id based CSS rules and using classes in JavaScript.
Summing up everything, the following is what we achieved by using the new approach for developing the mobile website:
  • The business logic is now completely separate from the UI code, and can be used independent of UI code.
  • The UI code has direct mapping with the jspx files. If a jspx file is modified, only its respective is modified.
  • Since all fields and HTML elements are defined in each module, changing ids of fields in jspx file requires just a single update in its module.
  • All JQuery dependent code has been moved to the ModuleHelper module. Although it might still require a lot of other changes, replacing JQuery with any other library requires minimal UI code changes.
  • Each HTML element is now uniquely identifiable by its module, even if the jspx file gets included multiple times on the same page.
  • Form validations and error handling are now completely removed from the UI code.

Further Reading:

Following are a few links for further reading on some basic JavaScript features and design patterns:
Functions in JavaScript are First Class Objects
JavaScript Closures
JavaScript Design Patterns