<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7953107657166087832</id><updated>2026-07-15T00:16:57.154+05:30</updated><category term="Analytics"/><category term="Digital Strategy"/><category term="Social Media"/><category term="BIg Data"/><category term="Cloud"/><category term="ESB EAI Service Adapters comparison"/><category term="Facebook"/><category term="Mobility"/><category term="SOA BPM ESB"/><category term="Security"/><category term="Spring AOP crosscutting concerns"/><category term="Twitter"/><category term="WS-Security"/><category term="Web Services"/><category term="express.js"/><category term="hibernate"/><category term="java"/><category term="javascript"/><category term="multi-tenant"/><category term="node.js"/><category term="reactive frameworks"/><category term="soa"/><title type='text'>Idea Fountain</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>65</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-2913947946871189484</id><published>2024-12-08T00:04:00.002+05:30</published><updated>2024-12-08T00:04:54.405+05:30</updated><title type='text'>Agent AI Workflows, Deja Vu?</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;LLMs have had a great run, up the hype cycle. After the initial euphoria, things seem to plateauing off in terms of potential usage, the burst of Generative AI not withstanding. Also the LLMs are not making much inroads into the super lucrative market of enterprise development. They have spent billions on evolving the models of these LLMs, the incremental evolution from here on can hardly pay the bills.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;Refer my earlier post on the difficulties of LLM getting to learn about custom enterprise data models. In fact the only way to make inroads into the enterprise market and get a piece of the pie, is by somehow making enterprise business process development, dependent on the LLM. &lt;/div&gt;&lt;p style=&quot;text-align: left;&quot;&gt;As things stand right now, it would be very difficult and time consuming to enable LLMs to directly understand custom business processes, so what is the next best strategy now? Enter Agentic workflows ....&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Every few years or so, this century, we have had technologies like EJBs, BPM, BPEL, ESB try to convince enterprises that they were the way to model business logic inside business processes. Well there is a new alternative which will now try to model business logic and processes, while being orchestrated by none other than the LLMs.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;The #AgenticAI workflows with their nodes, edges, human-in-the-loop, sub-graphs for sub-processes, workflow designing studios, deployment servers will have the ability to loop with exit conditions contrasting them from DAG based BPM flows. The agentic workflow is a classical state machine implementation controlled to an extent by the LLM, but dictated primarily by business logic any which ways.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Meanwhile the inherent complexity of any business process stays just the same, irrespective of the technology used. Many of the lower intricacies of the business process may still need to be modelled as service implementations with persistent domain data models. The autonomous decision making part is left completely at the risk of designers who design the agents, agentic workflows, with LLM providing limited control or &amp;lt;ahem&amp;gt; intelligence.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;The amount of sematic modelling involved in an advanced state machine, which will act as autonomous agents, is no trivial design exercise and maybe base agent reference implementations will evolve in due course to make business application development easier and less riskier.&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Are there less expensive options of leveraging LLMs intelligence, in the enterprise, as pin-point integrations points within a custom business process, apart from RAG based approach? Comment below.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Meanwhile, I am rushing off to continue learning #LangGraph, #Autogen and #CrewAI, since we all need to be in the game, right?&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/2913947946871189484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/2913947946871189484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/2913947946871189484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/2913947946871189484'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2024/12/agent-ai-workflows-deja-vu.html' title='Agent AI Workflows, Deja Vu?'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-4646173837386336363</id><published>2020-11-29T11:26:00.002+05:30</published><updated>2020-11-29T11:26:09.105+05:30</updated><title type='text'>Why I am starting to believe that time is an illusion</title><content type='html'>&lt;p&gt;We have refined our understanding of gravity from being a force of nature that attracts 2 masses, to gravity being merely the curvature of space-time to gravity being interpreted as time slowing down in space.&lt;/p&gt;&lt;p&gt;The other important ongoing discovery has to do with dark matter and dark energy which constitutes around 95% of our observable universe. Commensurate with evolving insights of dark matter and energy, dark energy at least seems to be the omnipresent energy in the vacuum of space, spread out over such large spaces that its detection is faint due to its density being very less.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I imagine, that dark matter may also on similar lines differ from ordinary matter, in that, it is much less dense and spread out over the vast expanse of inter galactic spaces. The current tug of war between our expanding universe v/s gravity, could then be seen as a war of equilibrium between normal matter/energy vs dark matter/energy, and clearly normal matter is getting rarefied, on the overall scale of the universe.&lt;/p&gt;&lt;p&gt;Next, lets for a moment assume that the nature of reality(matter and energy), truly is made up of E8 crystals or any other unit of reality, for that matter. So ordinary matter could be nothing but &quot;densely packed E8 crystals&quot; and dark matter could be &quot;very rarefied&quot; E8 crystals.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Time as we know it, is perceived by us, as beings made up of matter. Our perception of time primarily is from the point of view of how it appears in the &quot;ordinary matter&quot; portion of the universe. In the vacuum of space and in the dark matter part of the universe, is time just as relevant?&lt;br /&gt;&lt;br /&gt;The perception of time is linked to causality, as experienced by us in the macro universe.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Time in the macro universe might seem ubiquitous but at sub atomic and quantum scales, where wave nature, duality, uncertainty and randomness are the norm, does the linear flow of time, as in the macro universe even hold relevance?&lt;/p&gt;&lt;p&gt;Time needs a frame of reference and an observer, without these, being clear to us, over the expanse of the universe and dark matter, is time a relevant variable for study, of particle physics itself?&lt;br /&gt;&lt;br /&gt;Now can you blame me for tending to think, that time might be an illusion of our perception of the macro universe.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;-GG&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/4646173837386336363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/4646173837386336363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/4646173837386336363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/4646173837386336363'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2020/11/why-i-am-starting-to-believe-that-time.html' title='Why I am starting to believe that time is an illusion'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-6301781509095073758</id><published>2020-08-21T18:54:00.000+05:30</published><updated>2020-08-21T18:54:24.259+05:30</updated><title type='text'>Throttling Kafka Consumption - Dispelling Myths</title><content type='html'>&lt;p&gt;Kafka as a messaging broker was designed for high throughput publish and subscribe. At times this very fact can prove to be an issue, when being used in more traditionally designed transactional systems. For example if an application is consuming messages from a kafka topic and inserting, updating in a relational database, the high rate of consumption of kafka messages, can put pressure on transactional persistence in the RDBMS and cause exceptions. Hence there arises a need to throttle message consumption from a kafka topic.&lt;/p&gt;&lt;p&gt;Starting out, lets assume, that we are only considering the message consumption inside a single instance of a consumer (which may be a part of a bigger consumer group). So we have a single consumer instance, picking up kafka messages from a single partition of a topic.&lt;/p&gt;&lt;p&gt;Most kafka client frameworks, will implement a decent kafka consumer poll-loop, for reading kafka messages from the partition as soon as possible and then hand these messages over to client application, as fast as possible, but without waiting/blocking for the client application to process each message.&lt;/p&gt;&lt;p&gt;For single thread technologies like node js, the above can be an issue,in the sense that, the result is that the application starts processing large number of messages in parallel. Many will resort to kafka configuration parameters like below, to control the rate of consumption of messages from kafka, with very little success, for the reasons I mention below:&lt;/p&gt;&lt;p&gt;&lt;b&gt;fetch.min.bytes&lt;/b&gt; - This property allows a consumer to specify the minimum amount of data that it wants to receive from the broker when fetching records. If a broker receives a request for records from a consumer but the new records amount to fewer bytes than fetch.min.bytes, the broker will wait until more messages are available before sending the records back to the consumer.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;fetch.max.wait.ms&lt;/b&gt; -&amp;nbsp;By setting fetch.min.bytes, you tell Kafka to wait until it has enough data to send before responding to the consumer.If you set fetch.max.wait.ms to 100 ms and fetch.min.bytes to 1 MB, Kafka will receive a fetch request from the consumer and will respond with data either when it has 1 MB of data to return or after 100 ms, whichever happens first.&lt;/p&gt;&lt;p&gt;&lt;b&gt;max.partition.fetch.bytes&lt;/b&gt; -&amp;nbsp;This property controls the maximum number of bytes the server will return per partition.&lt;/p&gt;&lt;p&gt;&lt;b&gt;session.timeout.ms&lt;/b&gt; -&amp;nbsp;The amount of time a consumer can be out of contact with the brokers while still considered alive defaults to 10 seconds.&lt;/p&gt;&lt;p&gt;&lt;b&gt;max.poll.records&lt;/b&gt; -&amp;nbsp;This controls the maximum number of records that a single call to poll() will return.&lt;/p&gt;&lt;p&gt;&lt;b&gt;receive.buffer.bytes and send.buffer.bytes&lt;/b&gt; -&amp;nbsp;These are the sizes of the TCP send and receive buffers used by the sockets when writing and reading data.&lt;/p&gt;&lt;p&gt;&lt;i&gt;If we manipulate above values, messages will be fetched more frequently OR less frequently. But &lt;b&gt;if&amp;nbsp; already 1000s of messages are lying in the topic&lt;/b&gt;, it wont matter a lot, given that fetch from topic to consumer is very quick(micro seconds). The consumer will still feel a steady supply of almost parallel messages.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Even playing around with commit offsets, will never block consumption of messages but only influence&amp;nbsp;recovery, guaranteed delivery, once only delivery, etc. This will not be able to restrict super-fast, reading of messages by the consumer. (Its not like late acknowledgements, block, consumption of messages in traditional message brokers like JMS, MQ, etc)&lt;/i&gt;&lt;/p&gt;&lt;p&gt;The bottom line is that, the challenge of parallel consumption of messages in a kafka instance consumer, needs to be handled by the process/application and not by kafka configurations.&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Consumer Side Technology&lt;/b&gt;&lt;/h2&gt;&lt;p&gt;A much more important factor while dealing with throttling of kafka messages, is which tech/architecture you use, on the consumer side application.&lt;/p&gt;&lt;p&gt;Using Java / SpringBoot based consumer, will ensure that the consumer process runtime will be multi-thread-based and will be synchronous first or synchronous by default. The use of thread-pools in Java/Spring and given the fact that almost all calls in Java are synchronous by default, it is much easier to control the kafka message consumption in Java&lt;/p&gt;&lt;p&gt;Node JS based consumers are inherently single threaded an hence asynchronous first or asynchronous by default, using await, promises and callbacks in a way, that near-parallel consumption of kafka messages will be challenge, especially for less-experienced developers.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/6301781509095073758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/6301781509095073758' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/6301781509095073758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/6301781509095073758'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2020/08/throttling-kafka-consumption-dispelling.html' title='Throttling Kafka Consumption - Dispelling Myths'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-3683670964942917318</id><published>2019-11-18T17:28:00.004+05:30</published><updated>2019-11-18T17:42:19.235+05:30</updated><title type='text'>Process Mining - Practical Uses</title><content type='html'>&lt;span style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;Process mining is a family of techniques that support the analysis of business processes based on event logs. During process mining, specialized data mining algorithms are applied to event log data in order to identify trends, patterns and details contained in event logs, &lt;/span&gt;&lt;b style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;to auto-discover and paint process definitions of processes&lt;/b&gt;&lt;span style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;. Process mining can be used to discover processes from events or improve process efficiency by identifying bottlenecks and exceptions&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: , , &amp;quot;blinkmacsystemfont&amp;quot; , &amp;quot;segoe ui&amp;quot; , &amp;quot;roboto&amp;quot; , &amp;quot;helvetica neue&amp;quot; , &amp;quot;fira sans&amp;quot; , &amp;quot;ubuntu&amp;quot; , &amp;quot;oxygen&amp;quot; , &amp;quot;oxygen sans&amp;quot; , &amp;quot;cantarell&amp;quot; , &amp;quot;droid sans&amp;quot; , &amp;quot;apple color emoji&amp;quot; , &amp;quot;segoe ui emoji&amp;quot; , &amp;quot;segoe ui symbol&amp;quot; , &amp;quot;lucida grande&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;arial&amp;quot; , sans-serif; font-size: 14px; white-space: pre-wrap;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: , , &amp;quot;blinkmacsystemfont&amp;quot; , &amp;quot;segoe ui&amp;quot; , &amp;quot;roboto&amp;quot; , &amp;quot;helvetica neue&amp;quot; , &amp;quot;fira sans&amp;quot; , &amp;quot;ubuntu&amp;quot; , &amp;quot;oxygen&amp;quot; , &amp;quot;oxygen sans&amp;quot; , &amp;quot;cantarell&amp;quot; , &amp;quot;droid sans&amp;quot; , &amp;quot;apple color emoji&amp;quot; , &amp;quot;segoe ui emoji&amp;quot; , &amp;quot;segoe ui symbol&amp;quot; , &amp;quot;lucida grande&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;arial&amp;quot; , sans-serif; font-size: 14px; white-space: pre-wrap;&quot;&gt;By itself process mining has several applications in large enterprises, to discover or validate business processes (in finance, manufacturing and retail) merely from events and timestamps, but the exciting thing is that the same technique can be used to get insights into user/customer behaviors on your website and also aid in customer segmentation.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: , , &amp;quot;blinkmacsystemfont&amp;quot; , &amp;quot;segoe ui&amp;quot; , &amp;quot;roboto&amp;quot; , &amp;quot;helvetica neue&amp;quot; , &amp;quot;fira sans&amp;quot; , &amp;quot;ubuntu&amp;quot; , &amp;quot;oxygen&amp;quot; , &amp;quot;oxygen sans&amp;quot; , &amp;quot;cantarell&amp;quot; , &amp;quot;droid sans&amp;quot; , &amp;quot;apple color emoji&amp;quot; , &amp;quot;segoe ui emoji&amp;quot; , &amp;quot;segoe ui symbol&amp;quot; , &amp;quot;lucida grande&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;arial&amp;quot; , sans-serif; font-size: 14px; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-size: 14px; white-space: pre-wrap;&quot;&gt;Consider a simplistic apache web log (though much more detailed application logs can also be used)&lt;/span&gt;&lt;br /&gt;
&lt;b style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;127.0.0.1 - peter [9/Feb/2017:10:34:12 -0700] &quot;GET /login.html HTTP/2&quot; 200 1479&lt;/b&gt;&lt;br /&gt;
&lt;b style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;127.0.0.1 - peter [9/Feb/2017:10:34:12 -0700] &quot;GET /catalog.html HTTP/2&quot; 200 1479&lt;/b&gt;&lt;br /&gt;
&lt;b style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;127.0.0.1 - peter [9/Feb/2017:10:34:12 -0700] &quot;GET /checkout.html HTTP/2&quot; 200 1479&lt;/b&gt;&lt;br /&gt;
&lt;b style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;127.0.0.1 - peter [9/Feb/2017:10:34:12 -0700] &quot;GET /checkstatus.html HTTP/2&quot; 200 1479&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;
&lt;b style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;
&lt;span style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;The important pieces of information are the user id &quot;peter&quot;, the date timestamp and the URL visited which can proxy up for the user&#39;s intended action. The above log can be easily transformed into&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;Sample CSV file&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 14px; white-space: pre-wrap;&quot;&gt;&lt;b&gt;&amp;lt;user&amp;gt;,&amp;lt;action&amp;gt;,&amp;lt;action date&amp;gt;, &amp;lt;user attribute 1&amp;gt;, &amp;lt;user attribute 2&amp;gt;, &amp;lt;user attribute n&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
UserId,Action,StartTimeStamp,EndTimeStamp,PremiumCustomer,UserLocation,UserOccupation&lt;br /&gt;
Peter,Logged In,12-20-2017&amp;nbsp; 10:20:00 AM,12-20-2017&amp;nbsp; 10:25:00 AM,premium_customer,US,architect&lt;br /&gt;
Bob,Logged In,12-20-2017&amp;nbsp; 10:20:00 AM,12-21-2017&amp;nbsp; 10:25:00 AM,premium_customer,US,architect&lt;br /&gt;
Peter,Browsed Catalog,12-20-2017&amp;nbsp; 10:35:00 AM,12-20-2017&amp;nbsp; 10:40:00 AM,premium_customer,US,architect&lt;br /&gt;
Alice,Browsed Catalog,12-21-2017&amp;nbsp; 10:35:00 AM,12-21-2017&amp;nbsp; 10:40:00 AM,premium_customer,US,architect&lt;br /&gt;
Bob,Browsed Catalog,12-21-2017&amp;nbsp; 10:35:00 AM,12-21-2017&amp;nbsp; 10:40:00 AM,premium_customer,US,architect&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
The above CSV data can now to be fed into a process mining tool to generate the &quot;user/customer&#39;s&quot; interaction process, as he navigates and uses the website. This can give many insights into how customers are using our websites and what we can do to make things more convenient for them.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg49I3F7nmx3U9DEPN3ypDfk2kkdQ9YnXwh1jXqsLWSiMzk1IQWp2PREVwag7v4CdzKca-qNdL3IVIT2LNC-Lz2kzHaEPAfax2djIez8eSODaavlD0-V9zc0VvePRiltmqeblGITUYHIHKP/s1600/sample-ecomm-process-flow.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;322&quot; data-original-width=&quot;1109&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg49I3F7nmx3U9DEPN3ypDfk2kkdQ9YnXwh1jXqsLWSiMzk1IQWp2PREVwag7v4CdzKca-qNdL3IVIT2LNC-Lz2kzHaEPAfax2djIez8eSODaavlD0-V9zc0VvePRiltmqeblGITUYHIHKP/s1600/sample-ecomm-process-flow.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Statistics like what time duration is spent by each user in any of the activities can also be readily obtained as a report from the tool. The major deviations in the main process flow can also be denoted. Animations of the process flow, over a period of months can be played out within minutes to get insight into the activities that are bottle-necking the overall process.&lt;br /&gt;
&lt;br /&gt;
Instead of discovering processes for individual users we can generalize processes for say &quot;platinum customers&quot; by filtering the data within the process mining tool itself.&lt;br /&gt;
&lt;br /&gt;
Process Mining deals with Petrinet and BPMN notations of process definitions and some popular algorithms for process mining are alpha miner, inductive visual miner and fuzzy miner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/3683670964942917318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/3683670964942917318' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/3683670964942917318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/3683670964942917318'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2019/11/process-mining-applications.html' title='Process Mining - Practical Uses'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg49I3F7nmx3U9DEPN3ypDfk2kkdQ9YnXwh1jXqsLWSiMzk1IQWp2PREVwag7v4CdzKca-qNdL3IVIT2LNC-Lz2kzHaEPAfax2djIez8eSODaavlD0-V9zc0VvePRiltmqeblGITUYHIHKP/s72-c/sample-ecomm-process-flow.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-7067086831343633672</id><published>2019-11-10T19:18:00.001+05:30</published><updated>2019-11-14T12:13:16.823+05:30</updated><title type='text'>Notes on Enterprise Application Development Strategy</title><content type='html'>At the end of the day, technology is an enabler for extracting business value. Some sure fire ways to burn money needlessly, during enterprise application development are noted below. Use it as a checklist to guard against, in your own enterprise development. As always, use your own context, while weighing-in, any generic advice.&lt;br /&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Don&#39;t care why and what the end user actually wants. Its more important to impress top management, with a good-looking demo&lt;/li&gt;
&lt;li&gt;Using a particular tech because it is popular at google, netflix or facebook, irrespective of its applicability within your own context, especially NFR context&lt;/li&gt;
&lt;li&gt;No clarity about the WHY, obsessed with only the HOW&lt;/li&gt;
&lt;li&gt;Not able to contain scope creep and needless escalation of complexity&lt;/li&gt;
&lt;li&gt;First thought that comes up becomes the definitive design, no choices, no alternatives considered&lt;/li&gt;
&lt;li&gt;Resume driven or Ego driven, development by tech leads&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Why use a suitable tech, when a tougher, riskier, newer tech is at hand, no matter how irrelevant&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Underestimating integration and dependencies&lt;/li&gt;
&lt;li&gt;Committing to technology choices without understanding the full scope of functionality and the non-functional requirements(NFR) in detail&lt;/li&gt;
&lt;li&gt;Forgetting that no application is an island. Its important that an application can &quot;fit into&quot; the enterprise landscape in terms of security standards, IDAM (identity and access management), audit standards, deployment, reliability and business continuity standards&lt;/li&gt;
&lt;li&gt;No thoughts given for migration path from existing application/s&lt;/li&gt;
&lt;li&gt;Disproportionate emphasis on UI look and feel rather than UX and information models&lt;/li&gt;
&lt;li&gt;Re-invent the wheel, under the guise of tech bravado&lt;/li&gt;
&lt;li&gt;Dev Teaming mistakes&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Thinking that employing 10 mediocre developers, instead of 3 crack devs, will be better&lt;/li&gt;
&lt;li&gt;Believe the myth that application devs, still write framework level code&lt;/li&gt;
&lt;li&gt;Never acknowledge, that app devs now, require to use proper frameworks and APIs, rather than belt out algorithms and complex programs&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/7067086831343633672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/7067086831343633672' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/7067086831343633672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/7067086831343633672'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2019/11/notes-on-it-strategy.html' title='Notes on Enterprise Application Development Strategy'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-7166231769024051933</id><published>2019-10-21T13:31:00.003+05:30</published><updated>2019-10-21T13:32:06.632+05:30</updated><title type='text'>Blockchain - Usecases in supply chains</title><content type='html'>Supply Chains, are the lifeline of businesses globally. Most likely, your business will find itself between upstream suppliers and downstream sales channels/distributors/customers. The figure below indicates this topology succinctly.&lt;br /&gt;
&lt;br /&gt;
Generic Supply Chain connected via a Blockchain&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmMkHZFl3CbvcI5SfP_OKuMS8mYBJT8_YTFrM4K0OY9n-wgcHaOnMGFvBazZMTkeVHFBXANHmx4CuXvjvwPGeq32uWnV3yiPCif-9xyXDres45X1s_4cHta5Y0728sbZ6eynh9exuWm5vC/s1600/0.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;720&quot; data-original-width=&quot;1280&quot; height=&quot;360&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmMkHZFl3CbvcI5SfP_OKuMS8mYBJT8_YTFrM4K0OY9n-wgcHaOnMGFvBazZMTkeVHFBXANHmx4CuXvjvwPGeq32uWnV3yiPCif-9xyXDres45X1s_4cHta5Y0728sbZ6eynh9exuWm5vC/s640/0.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Your organizations ability to fulfillment of its sales orders, totally depends on how efficient, agile your supply chain is. Some of the areas where blockchain technology can add great business value are:&lt;br /&gt;
&lt;br /&gt;
Optimizing Inventory Costs&lt;br /&gt;
Though organizations have fairly automated internal processes, most still rely on antiquated ways of interacting with their suppliers and business partners, Orders can be placed over voice calls, email, logging into each other&#39;s portals, etc. Tracking of these orders status is never, in real time, mostly left to voice calls, email reminders, etc. In fact, it would not be uncommon for your organization to get notified of a supplier&#39;s delay in order fulfillment, close to your own, downstream, fulfillment commitments. By having, deep, blockchain-based integrations, with your supplier&#39;s ERP, you can ensure almost real-time notifications of any potential delays, in your order fulfillment. You can automate balancing of orders across your other suppliers as well.&lt;br /&gt;
&lt;br /&gt;
If your distributors/sales partners are also on the blockchain, any weakness in demand, can also be notified to your organization in real-time, so as to re-balance supplier-side orders. This will lead to highly optimized inventories and substantial reduction in inventory costs. De-risking from supply side outages due to a specific supplier is another collateral benefit.&lt;br /&gt;
&lt;br /&gt;
By having most of your suppliers on the chain, you will get unprecedented clarity about the big picture on the supply side, across all your suppliers. This can help you in coordinating receipt of goods from different suppliers, with a consolidated scheduling system based on blockchain data. This can further optimize the timing and logistics aspects of the inventory.&lt;br /&gt;
&lt;br /&gt;
Minimizing Quality Costs using the blockchain&lt;br /&gt;
With the blockchain in place, your organization can have selective access to your supplier&#39;s ERP Data, including their quality control data. Having this level of accurate data, you can choose to minimize redundant quality checks, at your end. This is the good example of using a blockchain to enable trust and optimize costs.&lt;br /&gt;
&lt;br /&gt;
Suppliers of a Supplier can also be brought onto the blockchain, to enable deeper and far reaching integration via the blockchain.&lt;br /&gt;
&lt;br /&gt;
A blockchain can be used very effectively to &quot;track the state&quot; of a logical unit of delivery across supplier&#39;s parts. For example, if your organization was making refrigerators, every part, being supplied, tracked with the various suppliers, can be co-related with the logical entity &quot;refrigerator 123&quot; on the blockchain, hence, at any given point in time, you could not only know that 30 compressors, 26 coolant tubes are being supplied to me, but also that, I will be able to get out 26 complete refrigerators to my customers.&lt;br /&gt;
&lt;br /&gt;
Bidding based supplier order management&lt;br /&gt;
The same trust based blockchain technology can be used to operate a bidding platform, to manage orders being issued out to the suppliers&lt;br /&gt;
&lt;br /&gt;
Why traditional integration technologies like API, will just not work?&lt;br /&gt;
Point to point integrations with multiple suppliers not are just not scalable, in the supply chain ecosystem. imagine a supplychain with 5 nodes, each talking to other via point to API calls. Blockchains, along with providing a decentralized datastore, to track &quot;shared state&quot;, also provide a standard stack for integration, at all peers, not to mention &quot;consistent versions&quot; of same distributed smart contracts for processing the data.&lt;br /&gt;
&lt;br /&gt;
The suppliers that you bring onto the blockchain, may be direct competitors, inherently having a lack of trust about using processes, business logic, databases and codebases, belonging to each other, but the decentralized blockchain, will make it possible, to bring all such parties onto a common platform, sharing data/state, business processes and code.</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/7166231769024051933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/7166231769024051933' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/7166231769024051933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/7166231769024051933'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2019/10/supply-chains-are-lifeline-of.html' title='Blockchain - Usecases in supply chains'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmMkHZFl3CbvcI5SfP_OKuMS8mYBJT8_YTFrM4K0OY9n-wgcHaOnMGFvBazZMTkeVHFBXANHmx4CuXvjvwPGeq32uWnV3yiPCif-9xyXDres45X1s_4cHta5Y0728sbZ6eynh9exuWm5vC/s72-c/0.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-2205566156605029367</id><published>2019-10-21T13:22:00.002+05:30</published><updated>2019-10-21T13:24:10.716+05:30</updated><title type='text'>Countering, Counterfeiting</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6r2S2mu6Z2s8z9o2oLc8kRW58Uv3E0DGEw7NKy0rHEgPBv91Zu_rSDXXEv9w15rwG7N5aXP58BuQl-Nk86SNRbJLnmb0TGlqFhahja42Yl-lqiJAT1tfY8FGOqvU8rOj5-tXXwSd4Hqwt/s1600/counterfeit.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;400&quot; data-original-width=&quot;800&quot; height=&quot;160&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6r2S2mu6Z2s8z9o2oLc8kRW58Uv3E0DGEw7NKy0rHEgPBv91Zu_rSDXXEv9w15rwG7N5aXP58BuQl-Nk86SNRbJLnmb0TGlqFhahja42Yl-lqiJAT1tfY8FGOqvU8rOj5-tXXwSd4Hqwt/s320/counterfeit.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
While researching into the practical applications of blockchain tech, in provenance, tracking and traceability, I came across claims that blockchain can help to tackle counterfeiting, which is a serious issue in the fashion, luxury and branded products industry.&lt;br /&gt;
&lt;br /&gt;
The general opinion seemed to be that its tough to fight counterfeiting because establishing authenticity of an original product item, over a cleverly counterfeited one, was a tough nut to crack (at affordable technologies).&lt;br /&gt;
&lt;br /&gt;
Lets get into the mind of counterfeiter then...Typically counterfeiters will reproduce a near-duplicate of the original, at a fraction of the cost, then package it exactly like an original and send it out to be sold. It would be next to impossible to catch a cleverly made and packaged counterfeit item.&lt;br /&gt;
&lt;br /&gt;
The barcodes and qrcodes on the item package can be copied to the T, as well and then pasted onto the duplicates package. Standard barcodes (EAN-13) contain only the manufacturer code and product category information, which is popularly recognized as a GS1 standard GTIN, like is typically used to scan retail products as POS terminals. But the real problem like I said is that, the entire barcode can be copied and put onto a duplicate item, making it indistinguishable from the original. Authenticity is sadly not guaranteed even if additional attributes about the product item were embedded into extended barcode versions like the GS1 Databar or GS1-128.&lt;br /&gt;
&lt;br /&gt;
For authenticity checking, the trick is to use 2 factor authentication. Imagine a qr code encoding a random number, printed on the outside packaging of a luxury product. Now another QR code with yet another encoded number present inside the product itself (say on the product lining or inside of the cap of the bottle). Now we have 2 numbers, one on the outside and one on the inside(can be accessed, only after breaking the seal of the product).&lt;br /&gt;
&lt;br /&gt;
A simple web page/mobile app can be developed to validate the compatibility of the inside number and the outside number. As long as the compatibility checking algorithm is secret (maybe using a magic number/s), the end user can just scan the outside and inside QR codes/numbers, to let the website/mobile app, determine if the product is authentic or counterfeit.&lt;br /&gt;
&lt;br /&gt;
Even if the counterfeiter manages to exactly copy, the outer packaging, he can never &quot;quess&quot; what the inside number should be, since he does not know the exact algorithm, that is used to derive/correlate to the inside number.&lt;br /&gt;
&lt;br /&gt;
The last problem to solve, is the possibility that the counterfeiter may get hold of a few good samples of &quot;valid&quot; number pairs and use them with all the counterfeits repeatedly ! This can be easily tracked, since the website/app is centralized and can keep track how many times the query for checking authenticity is being received and from what sources, mobiles, geo-locations etc&lt;br /&gt;
&lt;br /&gt;
Let know in the comments, any loopholes, I may have missed or any improvements you can think of.</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/2205566156605029367/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/2205566156605029367' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/2205566156605029367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/2205566156605029367'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2019/10/countering-counterfeiting.html' title='Countering, Counterfeiting'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6r2S2mu6Z2s8z9o2oLc8kRW58Uv3E0DGEw7NKy0rHEgPBv91Zu_rSDXXEv9w15rwG7N5aXP58BuQl-Nk86SNRbJLnmb0TGlqFhahja42Yl-lqiJAT1tfY8FGOqvU8rOj5-tXXwSd4Hqwt/s72-c/counterfeit.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-7963174639184693978</id><published>2019-08-13T16:51:00.002+05:30</published><updated>2019-08-13T16:51:33.042+05:30</updated><title type='text'>Integrating existing enterprise apps with blockchain</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPUeJ-elgcETT-cPyXILhbbEVh6_Td4MsHwMFIH_JQIuKaEPe5hyIaixnU-w1cZ-JDhpb8nToPYmLYLxHkLZlVpIhWGEG9S7jodseLUypQzgPYpyzXR74FC1opP-bDrsLVouzaHY1VpZOH/s1600/integration-plugs.jpeg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;157&quot; data-original-width=&quot;322&quot; height=&quot;195&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPUeJ-elgcETT-cPyXILhbbEVh6_Td4MsHwMFIH_JQIuKaEPe5hyIaixnU-w1cZ-JDhpb8nToPYmLYLxHkLZlVpIhWGEG9S7jodseLUypQzgPYpyzXR74FC1opP-bDrsLVouzaHY1VpZOH/s400/integration-plugs.jpeg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Lowering the barrier to entry, is key for increased adoption of blockchain based technologies into enterprises. Irrespective of the business value, that blockchains bring, there is a need to decrease the cost, pain and risk of integrating blockchains with existing applications in the enterprise.&lt;br /&gt;
&lt;br /&gt;
Most large enterprises today, have established ERPs, CRMs, or cloud native custom applications, running 24 x 7. It makes sense to interface the new blockchain tech, harmoniously into the enterprise architecture landscape.&lt;br /&gt;
&lt;br /&gt;
Its quite practical to assume that, most organizations, while they would want to participate in a blockchain and get all the benefits, will most likely be reluctant to do any major modifications to their existing enterprise apps. The need of the hour is, to ease ingestion of data onto the blockchain, without requiring expensive UI based / operational alternatives.&lt;br /&gt;
&lt;br /&gt;
Presented below are a few ideas, for ingesting data onto blockchains, in an automated and batched manner, with minimal integration development and risk. Refer my earlier article about, wrapping up blockchain clients inside REST webservices, the below ideas can be used in conjunction with the REST adapters.&lt;br /&gt;
&lt;br /&gt;
ERP Application Logs &amp;gt;&amp;gt; Logstash &amp;gt;&amp;gt; Http Post to Blockchain REST adapters &amp;gt;&amp;gt; Blockchain&lt;br /&gt;
&lt;br /&gt;
Existing Application JDBC DB &amp;gt;&amp;gt; Database Polling &amp;gt;&amp;gt; Http Post to Blockchain REST adapters &amp;gt;&amp;gt; Blockchain&lt;br /&gt;
&lt;br /&gt;
Existing Application publish message &amp;gt;&amp;gt; Topics (Message Provider/Kafka) &amp;gt;&amp;gt; Logstash &amp;gt;&amp;gt; Http Post to Blockchain REST adapters &amp;gt;&amp;gt; Blockchain&lt;br /&gt;
&lt;br /&gt;
When the need for capturing data onto the blockchain is critical, more reliable and resilient, pipeline with Kafka based topics can be used.</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/7963174639184693978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/7963174639184693978' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/7963174639184693978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/7963174639184693978'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2019/08/integrating-existing-enterprise-apps.html' title='Integrating existing enterprise apps with blockchain'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPUeJ-elgcETT-cPyXILhbbEVh6_Td4MsHwMFIH_JQIuKaEPe5hyIaixnU-w1cZ-JDhpb8nToPYmLYLxHkLZlVpIhWGEG9S7jodseLUypQzgPYpyzXR74FC1opP-bDrsLVouzaHY1VpZOH/s72-c/integration-plugs.jpeg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-1203756596242186632</id><published>2019-08-10T12:35:00.000+05:30</published><updated>2019-08-10T12:35:03.166+05:30</updated><title type='text'>Blockchain alternative to API integration across enterprises</title><content type='html'>&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXskQU_NIsDL8D69Q6p4Zj05h6sDdwuwQwrxDofllk7_BzqZ8GpOxF9cKWZf8CAPywYd_UDyk5M8ecL8J2nmG5T5OI5hxNy4zfnj6e6Fz6POIP80G61fyQm2ZsUiU4aQj1CmKyMHr2mB3D/s1600/generic-blockchain-sample.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;252&quot; data-original-width=&quot;636&quot; height=&quot;251&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXskQU_NIsDL8D69Q6p4Zj05h6sDdwuwQwrxDofllk7_BzqZ8GpOxF9cKWZf8CAPywYd_UDyk5M8ecL8J2nmG5T5OI5hxNy4zfnj6e6Fz6POIP80G61fyQm2ZsUiU4aQj1CmKyMHr2mB3D/s640/generic-blockchain-sample.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
What is the go-to solution when 2 enterprises wish to communicate with each other. Right! Its via APIs, that too using REST APIs, with appropriate security in place.&lt;br /&gt;
&lt;br /&gt;
Typically this involves one of the companies developing webservices and exposing those services, to be consumed by another enterprise. There are several constraining factors for this kind enterprise integration:&lt;br /&gt;
&lt;br /&gt;
The webservices paradigm is uni-directional, that is, if org A, invokes a webservice hosted by org B, for org B, to confirm that desired state changes have occured, org B must call another webservice hosted by org A. This is essentially the issue, that the webservice calls are stateless. There is no state sharing at all between the organizations.&lt;br /&gt;
&lt;br /&gt;
For true leverage and reuse of the webservices, there needs to be orchestration at the consumer side. This orchestration is not transparent to the provider of webservices.&lt;br /&gt;
&lt;br /&gt;
The communication is primarily point to point. So the interactions, cannot be scaled easily if newer participants join in. Imagine 4 organizations, each one trying to call services into others and trying to keep track of some shared state, using and exposing status calls&lt;br /&gt;
&lt;br /&gt;
All the above issues are elegantly solved using the &quot;shared state&quot; paradigm of blockchain. All participants talk to the blockchain almost as if it were a logical messaging bus, but more importantly, the bus is not just a physical connection, but maintains state in distributed ledger and also has smart contracts that can house, common and transparent pieces of code, that can be shared across the un-trusting organizations aka partners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/1203756596242186632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/1203756596242186632' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1203756596242186632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1203756596242186632'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2019/08/blockchain-alternative-to-api.html' title='Blockchain alternative to API integration across enterprises'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXskQU_NIsDL8D69Q6p4Zj05h6sDdwuwQwrxDofllk7_BzqZ8GpOxF9cKWZf8CAPywYd_UDyk5M8ecL8J2nmG5T5OI5hxNy4zfnj6e6Fz6POIP80G61fyQm2ZsUiU4aQj1CmKyMHr2mB3D/s72-c/generic-blockchain-sample.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-684230243215376530</id><published>2017-10-03T18:32:00.002+05:30</published><updated>2017-10-03T18:40:38.828+05:30</updated><title type='text'>Server to server API calls Security</title><content type='html'>&lt;span style=&quot;background-color: white; color: rgba(0 , 0 , 0 , 0.7); font-family: &amp;quot;source sans pro&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;arial&amp;quot; , sans-serif , &amp;quot;hiragino kaku gothic pro&amp;quot; , &amp;quot;meiryo&amp;quot; , &amp;quot;hiragino sans gb w3&amp;quot; , &amp;quot;noto naskh arabic&amp;quot; , &amp;quot;droid arabic naskh&amp;quot; , &amp;quot;geeza pro&amp;quot; , &amp;quot;simplified arabic&amp;quot; , &amp;quot;noto sans thai&amp;quot; , &amp;quot;thonburi&amp;quot; , &amp;quot;dokchampa&amp;quot; , &amp;quot;droid sans thai&amp;quot; , &amp;quot;droid sans fallback&amp;quot; , , &amp;quot;.sfnsdisplay-regular&amp;quot; , &amp;quot;heiti sc&amp;quot; , &amp;quot;microsoft yahei&amp;quot; , &amp;quot;segoe ui&amp;quot;; font-size: 15px; white-space: pre-wrap;&quot;&gt;Calling Partner APIs from our application servers is a common use-case, a quick summary of options for securing such Server to server API calls
&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white; color: rgba(0 , 0 , 0 , 0.7); font-family: &amp;quot;source sans pro&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;arial&amp;quot; , sans-serif , &amp;quot;hiragino kaku gothic pro&amp;quot; , &amp;quot;meiryo&amp;quot; , &amp;quot;hiragino sans gb w3&amp;quot; , &amp;quot;noto naskh arabic&amp;quot; , &amp;quot;droid arabic naskh&amp;quot; , &amp;quot;geeza pro&amp;quot; , &amp;quot;simplified arabic&amp;quot; , &amp;quot;noto sans thai&amp;quot; , &amp;quot;thonburi&amp;quot; , &amp;quot;dokchampa&amp;quot; , &amp;quot;droid sans thai&amp;quot; , &amp;quot;droid sans fallback&amp;quot; , , &amp;quot;.sfnsdisplay-regular&amp;quot; , &amp;quot;heiti sc&amp;quot; , &amp;quot;microsoft yahei&amp;quot; , &amp;quot;segoe ui&amp;quot;; font-size: 15px; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5QcDFYg0uub3B4QRhbCwRZIjKsQ4RQIq0rmzf_75bPB1nAjkmFOH-kw8Fv3xBsUrJwUmM0-S8ohNvzhRxpfupuimf2eTgnHwbyx94utNwMVZUutZI0QtHB2JKKDTD7Dp9MIwzLjGxlmNB/s1600/Server2Server-Security.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;720&quot; data-original-width=&quot;1280&quot; height=&quot;360&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5QcDFYg0uub3B4QRhbCwRZIjKsQ4RQIq0rmzf_75bPB1nAjkmFOH-kw8Fv3xBsUrJwUmM0-S8ohNvzhRxpfupuimf2eTgnHwbyx94utNwMVZUutZI0QtHB2JKKDTD7Dp9MIwzLjGxlmNB/s640/Server2Server-Security.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/684230243215376530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/684230243215376530' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/684230243215376530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/684230243215376530'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2017/10/server-to-server-api-calls-security.html' title='Server to server API calls Security'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5QcDFYg0uub3B4QRhbCwRZIjKsQ4RQIq0rmzf_75bPB1nAjkmFOH-kw8Fv3xBsUrJwUmM0-S8ohNvzhRxpfupuimf2eTgnHwbyx94utNwMVZUutZI0QtHB2JKKDTD7Dp9MIwzLjGxlmNB/s72-c/Server2Server-Security.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-3994795440273216484</id><published>2017-08-13T22:38:00.002+05:30</published><updated>2017-08-13T22:44:30.472+05:30</updated><title type='text'>Cloud, Elasticity and Microservices</title><content type='html'>Many enterprise customers are being seen talking about moving to the cloud and adopting microservices based architectures. This is especially seen in the Indian BFSI domain. Heres my two cents at how the things are evolving logically and trade offs that all BFSI Businesses should be aware of.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The incentive to move to the cloud&lt;/b&gt;&lt;br /&gt;
Conventional wisdom is slowly but surely tilting towards moving IT infrastructures to secure public clouds like AWS, Azure and IBM Bluemix. The reasons are many and varied and well established by now, I wont regurgitate the same here again. Irrespective of the particular reason for moving the newer enterprise applications to the cloud, it makes sense to ensure that the underlying applications can &quot;leverage&quot; the cloud based infrastructures to the fullest.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Elasticity is important&lt;/b&gt;&lt;br /&gt;
The cloud provides for dynamic provisioning of resources like processing power, storage, network bandwidth, etc. It then follows logically, that enterprise applications that are deployed on the cloud should be fully capable of &quot;leveraging&quot; this elasticity of the cloud to &quot;scale out&quot; over resources.&lt;br /&gt;
Most importantly since clouds are pay-as-you-go model, if the underlying architecture is able to &quot;scale down&quot; automatically, when customer demand is low, the cloud costs for running applications can be optimized. Such architectures which can optimize operating costs of the cloud are very desirable. Mind you, in the cloud, being able to &quot;scale down&quot; as per demand is not just a good-to-have but rather an imperative that has direct cost implications.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Enter Microservices&lt;/b&gt;&lt;br /&gt;
In a monolithic application based approach including app servers or ESBs or service orchestration containers, the size of the monolith restricts the extent to which the scale-down can occur. Hence the architectural approach of microservices which are much more granular lends itself to better scale down capabilities, along with various important&amp;nbsp;&lt;a href=&quot;https://dzone.com/articles/benefits-amp-examples-of-microservices-architectur&quot;&gt;technical advantages of microservices&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Containerization and choices&lt;/b&gt;&lt;br /&gt;
OK so microservices lend themselves well to cloud deployments, due to their granularity! But managing microservices, monitoring them, ensuring fault tolerance, reliability, scalability, is now a challenging task. Using light weight and proven container technologies like docker becomes inevitable. Docker also provides the much needed portability.&lt;br /&gt;
But managing the containers can itself become a complex task. Using a container management tool like docker swarm is good for less complex deployments and if you need to a single out of the box solution for container management. For more complex enterprise wide deployments a open source and portable and pluggable docker management framework like kubernetes is &amp;nbsp;much more practical.&lt;br /&gt;
For a &lt;a href=&quot;https://www.upcloud.com/blog/docker-swarm-vs-kubernetes/&quot;&gt;quick compare between swarm and kubernetes&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
In addition, the docker container will need some deep integrations with your cloud provider, remember all this is running on the cloud ;-)&lt;br /&gt;
Here too, we have cloud provider based solutions like EC2&#39;s Container service which can be considered to be &lt;a href=&quot;https://www.stratoscale.com/blog/kubernetes/ec2-container-service-vs-kubernetes/&quot;&gt;alternatives to kubernetes&lt;/a&gt;. But be aware that choosing a cloud provider based container management solution will mean no portability and vendor lock-in with your cloud provider&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The architectural shift to microservices, is just the tip of the ice berg when considering your move to the cloud. In subsequent articles I will be talking about other aspects of your move to the cloud, which will affect the way your enterprise applications interact with the world. Some topics I intend to cover are Security and using API Gateways for integrations.&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/3994795440273216484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/3994795440273216484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/3994795440273216484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/3994795440273216484'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2017/08/cloud-elasticity-and-microservices.html' title='Cloud, Elasticity and Microservices'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-1375610810471730745</id><published>2017-06-11T18:06:00.000+05:30</published><updated>2017-06-11T18:06:45.550+05:30</updated><title type='text'>Spark Quick Review : Study Notes </title><content type='html'>&lt;span style=&quot;background-color: white; color: #1d1f22; font-family: &amp;quot;helvetica neue&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;arial&amp;quot; , sans-serif; font-size: 14px;&quot;&gt;The main abstraction Spark provides is a&amp;nbsp;&lt;/span&gt;&lt;em style=&quot;background-color: white; color: #1d1f22; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; font-size: 14px;&quot;&gt;resilient distributed dataset&lt;/em&gt;&lt;span style=&quot;background-color: white; color: #1d1f22; font-family: &amp;quot;helvetica neue&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;arial&amp;quot; , sans-serif; font-size: 14px;&quot;&gt;&amp;nbsp;(RDD), which is a collection of elements partitioned across the nodes of the cluster that can be operated on in parallel. RDDs are created by starting with a file in the Hadoop file system (or any other Hadoop-supported file system), or an existing Scala collection in the driver program, and transforming it. Users may also ask Spark to&amp;nbsp;&lt;/span&gt;&lt;em style=&quot;background-color: white; color: #1d1f22; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; font-size: 14px;&quot;&gt;persist&lt;/em&gt;&lt;span style=&quot;background-color: white; color: #1d1f22; font-family: &amp;quot;helvetica neue&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;arial&amp;quot; , sans-serif; font-size: 14px;&quot;&gt;&amp;nbsp;an RDD in memory, allowing it to be reused efficiently across parallel operations. Finally, RDDs automatically recover from node failures.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: #1d1f22; font-family: &amp;quot;helvetica neue&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;arial&amp;quot; , sans-serif; font-size: 14px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;background-color: white; color: #1d1f22; font-family: &amp;quot;helvetica neue&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;arial&amp;quot; , sans-serif; font-size: 14px;&quot;&gt;Driver program&#39;s in memory array can be converted to distributed data structure using parallelize&lt;/span&gt;&lt;br /&gt;
&lt;pre style=&quot;background-color: whitesmoke; border-radius: 4px; border: 1px solid rgba(0, 0, 0, 0.15); color: #333333; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; font-size: 12px; line-height: 20px; margin-bottom: 10px; padding: 9.5px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot; style=&quot;background: transparent; border-radius: 3px; border: 0px; color: inherit; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; padding: 0px;&quot;&gt;&lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;asList&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;JavaRDD&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distData&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sc&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;parallelize&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Spark can create distributed datasets from any storage source supported by Hadoop, including your local file system, HDFS, Cassandra, HBase, Amazon S3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: whitesmoke; border-radius: 4px; border: 1px solid rgba(0, 0, 0, 0.15); color: #333333; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; font-size: 12px; line-height: 20px; margin-bottom: 10px; padding: 9.5px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot; style=&quot;background: transparent; border-radius: 3px; border: 0px; color: inherit; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; padding: 0px;&quot;&gt;&lt;span class=&quot;n&quot;&gt;JavaRDD&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distFile&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sc&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;textFile&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;color: #4070a0;&quot;&gt;&quot;data.txt&quot;&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
RDDs support two types of operations: &lt;b&gt;transformations&lt;/b&gt;, which create a new dataset from an existing one, and &lt;b&gt;actions&lt;/b&gt;, which return a value to the driver program after running a computation on the dataset.&lt;br /&gt;
For example, map is a transformation that passes each dataset element through a function and returns a new RDD representing the results. On the other hand, reduce is an action that aggregates all the elements of the RDD using some function and returns the final result to the driver program (although there is also a parallel reduceByKey that returns a distributed dataset).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Since RDDs are distributed data stuctures, something special needs to be done to count elements inside RDD.&lt;br /&gt;
&lt;br /&gt;
// Wrong: Don&#39;t do this!!&lt;br /&gt;
rdd.foreach(x -&amp;gt; counter += x);&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white; color: #444444; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; font-size: 12px;&quot;&gt;rdd.collect().foreach(println) &amp;nbsp;//can give out of memory since all data brought to drivernode&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;background-color: white; color: #444444; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; font-size: 12px;&quot;&gt;rdd.take(100).foreach(println)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Total Character Count Example&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: whitesmoke; border-radius: 4px; border: 1px solid rgba(0, 0, 0, 0.15); color: #333333; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; font-size: 12px; line-height: 20px; margin-bottom: 10px; padding: 9.5px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot; style=&quot;background: transparent; border-radius: 3px; border: 0px; color: inherit; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; padding: 0px;&quot;&gt;&lt;span class=&quot;n&quot;&gt;JavaRDD&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sc&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;textFile&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;color: #4070a0;&quot;&gt;&quot;data.txt&quot;&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;JavaRDD&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lineLengths&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;kt&quot; style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;totalLength&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lineLengths&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
The following code uses the reduceByKey operation on key-value pairs to count how many times each line of text occurs in a file:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: whitesmoke; border-radius: 4px; border: 1px solid rgba(0, 0, 0, 0.15); color: #333333; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; font-size: 12px; line-height: 20px; margin-bottom: 10px; padding: 9.5px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot; style=&quot;background: transparent; border-radius: 3px; border: 0px; color: inherit; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; padding: 0px;&quot;&gt;&lt;span class=&quot;nc&quot; style=&quot;color: #0e84b5; font-weight: bold;&quot;&gt;JavaRDD&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot; style=&quot;color: #0e84b5; font-weight: bold;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;k&quot; style=&quot;color: #007020; font-weight: bold;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sc&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textFile&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;color: #4070a0;&quot;&gt;&quot;data.txt&quot;&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot; style=&quot;color: #0e84b5; font-weight: bold;&quot;&gt;JavaPairRDD&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot; style=&quot;color: #0e84b5; font-weight: bold;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot; style=&quot;color: #0e84b5; font-weight: bold;&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pairs&lt;/span&gt; &lt;span class=&quot;k&quot; style=&quot;color: #007020; font-weight: bold;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mapToPair&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot; style=&quot;color: #007020; font-weight: bold;&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot; style=&quot;color: #0e84b5; font-weight: bold;&quot;&gt;Tuple2&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nc&quot; style=&quot;color: #0e84b5; font-weight: bold;&quot;&gt;JavaPairRDD&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot; style=&quot;color: #0e84b5; font-weight: bold;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot; style=&quot;color: #0e84b5; font-weight: bold;&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counts&lt;/span&gt; &lt;span class=&quot;k&quot; style=&quot;color: #007020; font-weight: bold;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reduceByKey&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Filter lines in a file for occurence of string &quot;ganesh&quot;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;pl-k&quot; style=&quot;background-color: white; box-sizing: border-box; color: #a71d5d; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;JavaRDD&amp;lt;&lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box; color: #333333;&quot;&gt;String&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt; logData &lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;background-color: white; box-sizing: border-box; color: #a71d5d; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt; sc&lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;background-color: white; box-sizing: border-box; color: #a71d5d; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;textFile(logFile)&lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;background-color: white; box-sizing: border-box; color: #a71d5d; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;cache();&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;pl-k&quot; style=&quot;background-color: white; box-sizing: border-box; color: #a71d5d; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;JavaRDD&amp;lt;&lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box; color: #333333;&quot;&gt;String&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt; retData &lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;background-color: white; box-sizing: border-box; color: #a71d5d; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt; logData&lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;background-color: white; box-sizing: border-box; color: #a71d5d; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;filter(s &lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;background-color: white; box-sizing: border-box; color: #a71d5d; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;background-color: white; box-sizing: border-box; color: #a71d5d; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt; s&lt;/span&gt;&lt;span class=&quot;pl-k&quot; style=&quot;background-color: white; box-sizing: border-box; color: #a71d5d; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;contains(&lt;/span&gt;&lt;span class=&quot;pl-s&quot; style=&quot;background-color: white; box-sizing: border-box; color: #183691; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;&lt;span class=&quot;pl-pds&quot; style=&quot;box-sizing: border-box;&quot;&gt;&quot;&lt;/span&gt;ganesh&lt;span class=&quot;pl-pds&quot; style=&quot;box-sizing: border-box;&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;));&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;background-color: white; color: #24292e; font-size: 12px; white-space: pre;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;background-color: white; color: #24292e; white-space: pre;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Different types of transformations and actions&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; white-space: pre;&quot;&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;https://spark.apache.org/docs/2.1.0/programming-guide.html&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; white-space: pre;&quot;&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;b style=&quot;background-color: white; color: #24292e; white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b style=&quot;background-color: white; color: #24292e; white-space: pre;&quot;&gt;Word Count&lt;/b&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; white-space: pre;&quot;&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;JavaRDD&amp;lt;String&amp;gt; words = lines.flatMap(s-&amp;gt;Arrays.asList(s.split(&quot; &quot;)).iterator());
JavaPairRDD&amp;lt;String, Integer&amp;gt; pairs = words.mapToPair(s -&amp;gt; new Tuple2(s, 1));
JavaPairRDD&amp;lt;String, Integer&amp;gt; counts = pairs.reduceByKey((a, b) -&amp;gt; a + b);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;background-color: white; color: #24292e; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 12px; white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;b&gt;Shared Variables&lt;/b&gt;&lt;br /&gt;
&lt;pre style=&quot;background-color: whitesmoke; border-radius: 4px; border: 1px solid rgba(0, 0, 0, 0.15); color: #333333; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; font-size: 12px; line-height: 20px; margin-bottom: 10px; padding: 9.5px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot; style=&quot;background: transparent; border-radius: 3px; border: 0px; color: inherit; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; padding: 0px;&quot;&gt;&lt;span class=&quot;n&quot;&gt;Broadcast&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot; style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;[]&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;broadcastVar&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sc&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;broadcast&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot; style=&quot;color: #007020; font-weight: bold;&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot; style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;broadcastVar&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;c1&quot; style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// returns [1, 2, 3]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: whitesmoke; border-radius: 4px; border: 1px solid rgba(0, 0, 0, 0.15); color: #333333; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; font-size: 12px; line-height: 20px; margin-bottom: 10px; padding: 9.5px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot; style=&quot;background: transparent; border-radius: 3px; border: 0px; color: inherit; font-family: Menlo, &amp;quot;Lucida Console&amp;quot;, monospace; padding: 0px;&quot;&gt;&lt;span class=&quot;n&quot;&gt;LongAccumulator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accum&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jsc&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;sc&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;longAccumulator&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sc&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;parallelize&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;asList&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accum&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;c1&quot; style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;c1&quot; style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// 10/09/29 18:41:08 INFO SparkContext: Tasks finished in 0.317106 s&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;accum&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot; style=&quot;color: #4070a0;&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;color: #666666;&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;c1&quot; style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// returns 10&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/1375610810471730745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/1375610810471730745' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1375610810471730745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1375610810471730745'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2017/06/spark-quick-review-study-notes.html' title='Spark Quick Review : Study Notes '/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-8081293975269851637</id><published>2015-11-19T09:45:00.001+05:30</published><updated>2015-11-19T09:45:09.784+05:30</updated><title type='text'>A gentle introduction to java based electronic trading using FIX</title><content type='html'>I recently had the chance to work on a java based web application which provides electronic trading functionality using &lt;b&gt;FIX(&lt;span style=&quot;background-color: white; font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , &amp;quot;garuda&amp;quot; , sans-serif; font-size: 12.8px; line-height: 17.92px;&quot;&gt;Financial Information eXchange)&lt;/span&gt;&lt;/b&gt;. Wanted to share some of my experiences in this post :-)&lt;br /&gt;
&lt;br /&gt;
Lets start out with the basics, though...&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Electronic Trading the big picture, where does FIX fit in?&lt;/b&gt;&lt;br /&gt;
Trade life cycle can be divided into the following phases:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Pre-Trade - analytics and price discovery&lt;/li&gt;
&lt;li&gt;Trade - order creation and execution&lt;/li&gt;
&lt;li&gt;Post Trade - clearing, allocation and settlement&lt;/li&gt;
&lt;li&gt;Post Settlement - risk mgmt, profit/loss account, position monitoring&lt;/li&gt;
&lt;/ol&gt;
FIX is mostly used in the Phases 1 and 2, whereas SWIFT is used in Phase 3 and beyond.&lt;br /&gt;
&lt;br /&gt;
FIX protocol features like quote(RFQ), Indication of Interest (IOI) are used for price discovery, whereas features like DealAtQuote, Market Order and Limit Order are used for order placement.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;How FIX is relevant &amp;nbsp;| &lt;a href=&quot;http://www.fixtradingcommunity.org/pg/main/who-uses-fix/fix-version&quot;&gt;Who Uses FIX&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
FIX® has become the way the world trades. Virtually every major stock exchange and investment bank uses FIX for electronic trading, alongside the world&#39;s largest mutual funds, money managers and thousands of smaller investment firms. Leading futures exchanges offer FIX connections and major bond dealers either have or are implementing them. Identifying an exact number of users is impossible, as FIX is a free and open standard, but it is very clear that the world’s financial community now speaks FIX.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Enterprise apps - Using Open Source QuickFixJ, the java library for FIX&lt;/b&gt;&lt;br /&gt;
Most enterprise applications, act as the BUY side of FIX protocol ie these applications place trade requests, to the SELL side of FIX, which is provided by vendors like&amp;nbsp;&lt;a href=&quot;https://www.winterflood.com/electronic-trading/index.html&quot;&gt;winterflood&lt;/a&gt;, which have connectivity to stock markets, traders, etc and enterprise applications require to, send FIX messages to vendor&#39;s FIX engine.&lt;br /&gt;
&lt;br /&gt;
In order to be able to interface with a FIX engine, of a provider like &lt;a href=&quot;https://www.winterflood.com/electronic-trading/index.html&quot;&gt;winterflood&lt;/a&gt;, using java code, there is an excellent open source framework called &lt;a href=&quot;http://www.quickfixj.org/quickfixj/&quot;&gt;QuickFixJ&lt;/a&gt;. This is a java library which can be used as a JVM embedded FIX engine. &lt;a href=&quot;http://www.quickfixj.org/documentation/&quot;&gt;Detailed documentation&lt;/a&gt; can be found at their website.&lt;br /&gt;
&lt;br /&gt;
In following article, the java code I will &amp;nbsp;be show-casing code that uses the QuickFixJ APIs&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Intro to common FIX flows&lt;/b&gt;&lt;br /&gt;
First, your application needs to communicate with a vendor who provides electronic trading services. Such vendors have a FIX server running with electronic trading capabilities and DMA(direct market access).&lt;br /&gt;
&lt;br /&gt;
The whole idea is that our application will send a FIX message asking for a trade to be executed, to the vendors FIX engine. The vendor service will execute the trade and send back a response to our application. The responses are always asynchronous and can come in delayed or not at all.&lt;br /&gt;
&lt;br /&gt;
Such trade instructions between our application and vendor FIX engine, using FIX messages format and protocol are called logically as FIX trade flows.&lt;br /&gt;
&lt;br /&gt;
There are typically huge number of trade flow, sub-flows, combinations, varied responses, but the trick is to narrow down the number of trade flows by pre-deciding with vendor, which trade flows we will consider and also clamp down on the possible requests and responses.&lt;br /&gt;
&lt;br /&gt;
This &lt;b&gt;logical ring fencing of the possible trade flows&lt;/b&gt; will ensure, you can provide robust, deterministic functionality related to electronic trading, in your own application.&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Quote with Deal At Quote Order&lt;/b&gt;&lt;br /&gt;
The most common trade interaction which can be done during market hours is the Quote and Deal functionality.&lt;br /&gt;
&lt;br /&gt;
As per this trade flow, user sends out a quote request, for a ticker/symbol in the form of a FIX Message of type R. Asynchronously, but within a few milli seconds, a Quote response is received by the application. This quote response contains the market price of the ticker/symbol as a quote. This price in quote is applicable only for a a few seconds say for 30 seconds&lt;br /&gt;
&lt;br /&gt;
The user now can send another FIX message within 30 seconds, asking to book order for above mentioned stock, with certain number of shares at the price agreed upon in the quote above&lt;br /&gt;
&lt;br /&gt;
A more interactive and verbose narrative is mentioned below, along with the sample FIX messages, good luck deciphering :-)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Quote and Deal&lt;/b&gt;&lt;br /&gt;
Quote (R) - give me quote for stock with symbol VOD&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;lt;20150923-07:47:20, FIX.4.2:APP-&amp;gt;VEND, outgoing&amp;gt; (8=FIX.4.2 9=194 35=R 34=2 49=APP 50=D2C 52=20150923-07:47:20.027 56=VEND 115=12345 131=1442994439993 146=1 55=VOD.L 48=GB00BH4HKS39 22=4 207=XLON 54=2 38=10 64=20150925 60=20150923-07:47:20.026 15=GBP 120=GBP 10=009 )&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Quote Response (S) - Unit market price for VOD is 2.445 pounds, valid for next 30 seconds&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;lt;20150923-07:47:20, FIX.4.2:APP-&amp;gt;VEND, incoming&amp;gt; (8=FIX.4.2 9=245 35=S 49=VEND 56=APP 34=2 52=20150923-07:47:20 131=1442994439993 117=X90FZI23H4719001 55=VOD.L 22=4 48=GB00BH4HKS39 167=CS 207=XLON 132=2.1325 134=3750 62=20150923-07:47:50 64=20150925 15=GBP 120=GBP 152=21.325 76=VENDOR 60=20150923-07:47:20 10=088 )&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Deal At Quote (D) - book an order for VOD @ 2.445 pounds for 100 shares&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;lt;20150923-07:47:20, FIX.4.2:APP-&amp;gt;VEND, outgoing&amp;gt; (8=FIX.4.2 9=238 35=D 34=3 49=APP 50=D2C 52=20150923-07:47:20.575 56=VEND 115=12345 11=1442994440565 15=GBP 21=1 22=4 38=10 40=D 44=2.1325 48=GB00BH4HKS39 54=2 55=VOD.L 59=4 60=20150923-07:47:20.575 63=3 64=20150925 117=X90FZI23H4719001 120=GBP 207=XLON 10=153 )&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Exceution Report (8) for VOD @ 2.445 pounds for 100 shares with order status=FILLED&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;lt;20150923-07:47:20, FIX.4.2:APP-&amp;gt;VEND, incoming&amp;gt; (8=FIX.4.2 9=359 35=8 49=VEND 56=APP 34=3 52=20150923-07:47:20 57=D2C 128=12345 1=WINTERG0 6=2.1325 11=1442994440565 14=10 15=GBP 17=b90FDI23H4720002 20=0 22=4 29=4 30=XLON 31=2.1325 32=10 37=b90FDI23H4720002 38=10 39=2 40=D 44=2.1325 48=GB00BH4HKS39 54=2 55=VOD.L 59=4 60=20150923-07:47:20 63=6 64=20150925 76=VENDOR 110=0 119=21.33 120=GBP 150=2 151=0 167=CS 207=XLON 10=244 )&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
other possible order status are: CANCELLED, &amp;nbsp;REJECTED, PARTIALLY_FILLED, etc&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
A quote can also be rejected, in which case a FIX message of type b is received by the application&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Market Order&lt;/b&gt;&lt;br /&gt;
A market order is an order request which asks to buy/sell a certain number of shares of a symbol at the best price, at the time of request.&lt;br /&gt;
&lt;br /&gt;
Market Order Request - 35=D order, 40=1 market, &amp;nbsp;54=2 sell, 55=VOD symbol, 38=110 num shares&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;lt;20150923-08:21:39, FIX.4.2:APP-&amp;gt;VEND, outgoing&amp;gt; (8=FIX.4.2 9=234 35=D 34=2 49=APP 50=D2C 52=20150923-08:21:39.383 56=VEND 115=12345 11=1442996499366 15=GBP 21=3 22=4 38=110 40=1 48=GB00BH4HKS39 54=2 55=VOD.L 59=6 60=20150923-08:21:39.380 63=3 64=20150925 120=GBP 126=20150925-08:21:39.381 207=XLON 10=110 )&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Execeution Report (8) with order status=FILLED&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;lt;20150923-08:21:39, FIX.4.2:APP-&amp;gt;VEND, incoming&amp;gt; (8=FIX.4.2 9=357 35=8 49=VEND 56=APP 34=2 52=20150923-08:21:39 57=D2C 128=12345 1=WINTERG0 6=2.1325 11=1442996499366 14=110 15=GBP 17=0D0FDI23I2139010 20=0 22=4 29=4 30=XLON 31=2.1325 32=110 37=0D0FDI23I2139010 38=110 39=2 40=1 44=2.1325 48=GB00BH4HKS39 54=2 55=VOD.L 59=3 60=20150923-08:21:39 63=6 64=20150925 76=VENDOR 119=234.58 120=GBP 150=2 151=0 167=CS 207=XLON 10=120 )&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Limit Order&lt;/b&gt;&lt;br /&gt;
A limit order is an order request which asks to buy/sell a certain number of shares of a symbol, when the stock price of the symbol, reaches a certain specified limit price.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Limit Order Request - 35=D order, 40=2 market, &amp;nbsp;54=2 sell, 55=VOD symbol, 38=110 num shares&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;lt;20151009-09:05:22, FIX.4.2:APP-&amp;gt;VEND, outgoing&amp;gt; (8=FIX.4.2 9=206 35=D 34=229 49=APP 50=D2C 52=20151009-09:05:22.933 56=VEND 115=12345 11=1444381522933 15=GBP 21=2 22=4 38=110 40=2 44=7.885 48=GB0004082847 54=1 55=STAN 59=0 60=20151009-09:05:22.933 63=3 120=GBP 207=XLON 10=112 )&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Exceution Report (8) with order status=NEW (Early ACK for limit order)&lt;br /&gt;
Limit orders will be filled only when limit is reached&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;lt;20151009-09:05:23, FIX.4.2:APP-&amp;gt;VEND, incoming&amp;gt; (8=FIX.4.2 9=296 35=8 49=VEND 56=APP 34=229 52=20151009-09:05:23 57=D2C 128=12345 6=0 11=1444381522933 14=0 15=GBP 17=y6u2743950 20=0 21=2 22=4 29=1 31=0 32=0 37=y6u2743950 38=110 39=0 40=2 44=7.885 48=GB0004082847 54=1 55=STAN 59=0 60=20151009-09:05:23 63=3 120=GBP 150=0 151=110 167=CS 198=y6u2743950 207=XLON 10=065 )&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
when limit price is reached, Exceution Report (8) with order status=FILLED&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;lt;20151009-09:22:41, FIX.4.2:APP-&amp;gt;VEND, incoming&amp;gt; (8=FIX.4.2 9=342 35=8 49=VEND 56=APP 34=268 52=20151009-09:22:41 57=D2C 128=12345 6=7.4 11=1444381522933 14=110 15=GBP 17=1040601735 20=0 21=2 22=4 29=4 30=XLON 31=7.4 32=110 37=y6u2743950 38=110 39=2 40=2 44=7.4 48=GB0004082847 54=1 55=STAN 59=0 60=20151009-09:22:41 63=3 64=20151013 76=VENDOR 119=814 120=GBP 150=2 151=0 152=814 155=0 167=CS 207=XLON 10=208 )&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;The Java Code (finally!)&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Quote request and deal-at-quote&lt;/b&gt;&lt;br /&gt;
Writing java code to submit a quote is as easy seen below&lt;br /&gt;
&lt;br /&gt;
quickfix.fix42.QuoteRequest quote = new quickfix.fix42.QuoteRequest(new QuoteReqID(quoteReqId));&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
//optionally set header feilds that your Trade Provider may require&lt;br /&gt;
quote.getHeader().setField(new OnBehalfOfCompID(ONBEHALF_COMP_ID));&lt;br /&gt;
quote.getHeader().setField(new SenderSubID(SENDER_SUB_ID));&lt;br /&gt;
&lt;br /&gt;
//create a new &#39;repeating group&#39; as per FIX spec&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
quickfix.fix42.QuoteRequest.NoRelatedSym group = new quickfix.fix42.QuoteRequest.NoRelatedSym();&lt;br /&gt;
&lt;br /&gt;
group.set(new Symbol(&quot;VOD&quot;));&lt;br /&gt;
group.set(new SecurityID(GB00BH4HKS39&amp;nbsp;)); //value of ISIN: GB00BH4HKS39&lt;br /&gt;
group.set(new IDSource(&quot;4&quot;)); &amp;nbsp;//4=ISIN, 2=SEDOL&lt;br /&gt;
group.set(new SecurityExchange(&quot;XLON&quot;)); &amp;nbsp;//stock exchange ID&lt;br /&gt;
group.set(Side.BUY); &amp;nbsp; //this could just as well be Side.SELL&lt;br /&gt;
&lt;br /&gt;
group.set(new OrderQty(10)); &amp;nbsp;//u can buy 10 shares of ticker VOD&lt;br /&gt;
//group.setField(new CashOrderQty(4000.00)); &amp;nbsp; &amp;nbsp;//u can buy shares worth 4000 instead of 10 shares&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
group.setField(new SettlCurrency(&quot;GBP&quot;)); &lt;br /&gt;
group.set(new Currency(&quot;GBP&quot;));&lt;br /&gt;
group.set(new TransactTime(new Date()));&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt; &lt;br /&gt;
quote.addGroup(group);&lt;br /&gt;
&lt;br /&gt;
System.out.println(&quot;getQuoteForVEND FIX42 message &quot;+quote);&lt;br /&gt;
Session.sendToTarget(quote, sessionId);&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;b&gt;Deal@Quote&lt;/b&gt;&lt;br /&gt;
Writing java code to submit a Deal@Quote is as easy seen below&lt;br /&gt;
NewOrderSingle order = new NewOrderSingle(new ClOrdID(orderId),&lt;br /&gt;
new HandlInst(HandlInst.AUTOMATED_EXECUTION_ORDER_PUBLIC),&lt;br /&gt;
new Symbol(&quot;VOD&quot;),&lt;br /&gt;
new Side(Side.SELL), new TransactTime(new Date()), new OrdType(OrdType.PREVIOUSLY_QUOTED));&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
//optionally set header feilds that your Trade Provider requires&lt;br /&gt;
order.getHeader().setField(new OnBehalfOfCompID(ONBEHALF_COMP_ID));&lt;br /&gt;
order.getHeader().setField(new SenderSubID(SENDER_SUB_ID));&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
order.set(new SecurityID(&quot;GB00BH4HKS39&quot;)); &amp;nbsp; //ISIN for ticker VOD&lt;br /&gt;
order.set(new IDSource(&quot;4&quot;)); &amp;nbsp;//4=ISIN, 2=SEDOL&lt;br /&gt;
order.set(new SettlmntTyp(SettlmntTyp.T_PLUS_2));&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
order.set(new SecurityExchange(&quot;XLON&quot;)); &amp;nbsp;//stock exchange london&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;order.set(new QuoteID(origQuoteId)); &amp;nbsp;//original quote ID&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;order.set(new Price(request.getPrice()));  //price of previous quote&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
//order.setField(new OrderQty(10)); //u can buy 10 shares of ticker VOD&lt;br /&gt;
order.set(new CashOrderQty(4000.00)); //u can buy shares worth 4000 instead of 10&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
order.set(new TimeInForce(TimeInForce.DAY)); &amp;nbsp;//can be other values like&lt;br /&gt;
order.set(new SettlCurrency(&quot;GBP&quot;));&lt;br /&gt;
order.set(new Currency(&quot;GBP&quot;));&lt;br /&gt;
&lt;br /&gt;
System.out.println(&quot;sending out DealAtQuotye FIX42 message &quot;+order);&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;-webkit-text-stroke-width: 0px; color: black; font-family: &#39;Times New Roman&#39;; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; margin: 0px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px;&quot;&gt;
Session.sendToTarget(order, sessionId);&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Market Order&lt;/b&gt;&lt;br /&gt;
Writing java code to send a market order is as easy as seen below&lt;br /&gt;
&lt;br /&gt;
NewOrderSingle order = new NewOrderSingle(new ClOrdID(orderId),&lt;br /&gt;
new HandlInst(HandlInst.AUTOMATED_EXECUTION_ORDER_PUBLIC),&lt;br /&gt;
new Symbol(&quot;VOD&quot;),&lt;br /&gt;
new Side(Side.SELL), new TransactTime(new Date()), new OrdType(OrdType.MARKET));&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt; &lt;br /&gt;
//optionally set header feilds that your Trade Provider requires&lt;br /&gt;
order.getHeader().setField(new OnBehalfOfCompID(ONBEHALF_COMP_ID));&lt;br /&gt;
order.getHeader().setField(new SenderSubID(SENDER_SUB_ID));&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
order.set(new SecurityID(&quot;GB00BH4HKS39&quot;)); &amp;nbsp; //ISIN for ticker VOD&lt;br /&gt;
order.set(new IDSource(&quot;4&quot;)); &amp;nbsp;//4=ISIN, 2=SEDOL&lt;br /&gt;
order.set(new SettlmntTyp(SettlmntTyp.T_PLUS_2));&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt; &lt;br /&gt;
order.set(new SecurityExchange(&quot;XLON&quot;)); &amp;nbsp;//stock exchange london&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt; &lt;br /&gt;
order.setField(new OrderQty(10)); //u can buy 10 shares of ticker VOD&lt;br /&gt;
//order.set(new CashOrderQty(4000.00)); //u can buy shares worth 4000 instead of 10&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt; &lt;br /&gt;
order.set(new TimeInForce(TimeInForce.DAY)); &amp;nbsp;//can be other values like&lt;br /&gt;
order.set(new SettlCurrency(&quot;GBP&quot;));&lt;br /&gt;
order.set(new Currency(&quot;GBP&quot;));&lt;br /&gt;
&lt;br /&gt;
System.out.println(&quot;sending out MarketOrderForVEND FIX42 message &quot;+order);&lt;br /&gt;
Session.sendToTarget(order, sessionId);&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Limit Order&lt;/b&gt;&lt;br /&gt;
Writing java code to send a Limit order is as easy as seen below.&lt;br /&gt;
Only change from above code is using the OrdType.LIMIT&lt;br /&gt;
&lt;br /&gt;
NewOrderSingle order = new NewOrderSingle(new ClOrdID(orderId),&lt;br /&gt;
new HandlInst(HandlInst.AUTOMATED_EXECUTION_ORDER_PUBLIC),&lt;br /&gt;
new Symbol(&quot;VOD&quot;),&lt;br /&gt;
new Side(Side.SELL), new TransactTime(new Date()), new OrdType(&lt;b&gt;OrdType.LIMIT&lt;/b&gt;));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Using the above concepts, frameworks and codes, provides some idea of the &amp;nbsp;electronic trading functionalities, that can be integrated into your java based enterprise application.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Cheers!&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/8081293975269851637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/8081293975269851637' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/8081293975269851637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/8081293975269851637'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2015/11/a-gentle-introduction-to-java-based.html' title='A gentle introduction to java based electronic trading using FIX'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-1650896162307006839</id><published>2015-08-28T12:00:00.002+05:30</published><updated>2015-08-31T10:09:05.276+05:30</updated><title type='text'>REST APIs for Simpler Payment Gateway Integration into your web and mobile apps</title><content type='html'>I recently had the chance to integrate the current web application I am working on with a popular UK based payment gateway for credit and debit cards, named&amp;nbsp;&lt;a href=&quot;https://online.worldpay.com/features&quot;&gt;Worldpay Online&lt;/a&gt;&amp;nbsp;. Carrying out the above integration was surprisingly easy and below are the details.&lt;br /&gt;
&lt;br /&gt;
Our requirement was that our end users should be able to pay for our application services using their debit / credit cards. I embarked on the payment gateway integration journey initially thinking of traditional ways of integration. We did not wish to incur the additional overhead of any PCI DSS compliance that occurs, if you choose to store any card details on your site. Hence, I started considering more traditional approaches like our site will redirect payment requests to the payment gateway hosted &quot;payment pages&quot;.&lt;br /&gt;
&lt;br /&gt;
These typically gives the end user the ability to choose their payment method, input their card details and ask for their card to be charged for relevant amounts.&lt;br /&gt;
&lt;br /&gt;
Even worldpay as our preferred payment gateway provider had these options under the integration type of &quot;HTML Redirect&quot;. However the main drawbacks of this kind of &quot;payment page&quot; based integration were as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;No control and limited customisation of the payment pages&lt;/li&gt;
&lt;li&gt;Lack of a strong application context while the user was on the payment pages&lt;/li&gt;
&lt;li&gt;The mechanism of gateway provider letting us know that the card was charged successfully made the whole process asynchronous, as it was a post back to our application servers&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Well, it turns out there is a much simpler approach available in most modern payment gateways. Using the payment gateways REST APIs. I used the worldpay online REST APIs, to quickly integrate the payment gateway into our application. Here I will talk a bit about my experience using the worldpay online payment APIs.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Though we use the payment REST APIs, we still do not need to have an PCI-DSS compliance. The reason is that we never capture or store the card details on our application. The entire process is broken down into 2 steps:&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Step 1: &lt;/b&gt;Our application displays inline or as pop-up a worldpay online screen. This worldpay screen captures the card details and gives back a temporary token to the application.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Step 2: &lt;/b&gt;The application uses the above temporary token and actually calls the REST payment API. The token acts as a proxy for the card details like card number, expiration date, CVV etc. Application never knows about card details, they are known only to worldpay online!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;The best part is that:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Except for a small portion of page which captures card details, rest of webpage is under applications control and hence customizable&lt;/li&gt;
&lt;li&gt;The actual REST API call is synchronous so error handling effort is reduced by a huge amount&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The actual payment REST call is as simple as shown below&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Example Request&lt;/h3&gt;
&lt;pre style=&quot;background-color: #fafafa; box-sizing: border-box; color: #333333; font-size: 16px; line-height: 25.6000003814697px; overflow-x: auto; padding: 10px !important;&quot;&gt;&lt;span class=&quot;highlight_js brainfuck&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;https://api&lt;/span&gt;.&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;worldpay&lt;/span&gt;.&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;com/v1/orders&lt;/span&gt;
    &lt;span class=&quot;literal&quot; style=&quot;box-sizing: border-box; color: #954121;&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;H&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;&quot;Authorization:your&lt;/span&gt;-&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;service&lt;/span&gt;-&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;key&quot;&lt;/span&gt;
    &lt;span class=&quot;literal&quot; style=&quot;box-sizing: border-box; color: #954121;&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;H&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;&quot;Content&lt;/span&gt;-&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;application/json&quot;&lt;/span&gt;
    &lt;span class=&quot;literal&quot; style=&quot;box-sizing: border-box; color: #954121;&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;POST&lt;/span&gt;
    &lt;span class=&quot;literal&quot; style=&quot;box-sizing: border-box; color: #954121;&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;d&lt;/span&gt;
&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;&#39;{&lt;/span&gt;
    &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;&quot;token&quot;&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;&quot;your&lt;/span&gt;-&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;token&quot;&lt;/span&gt;,
    &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;&quot;orderDescription&quot;&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;&quot;order&lt;/span&gt;-&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;description&quot;&lt;/span&gt;,
    &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;&quot;amount&quot;&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;500&lt;/span&gt;,
    &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;&quot;currencyCode&quot;&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;&quot;GBP&quot;&lt;/span&gt;
&lt;span class=&quot;comment&quot; style=&quot;box-sizing: border-box; color: #9b9bb9; font-style: italic;&quot;&gt;}&#39;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;h3&gt;
Example Response&lt;/h3&gt;
&lt;pre style=&quot;background-color: #fafafa; box-sizing: border-box; color: #333333; font-size: 16px; line-height: 25.6000003814697px; overflow-x: auto; padding: 10px !important;&quot;&gt;&lt;span class=&quot;highlight_js json&quot; style=&quot;box-sizing: border-box;&quot;&gt;{
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;orderCode&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;worldpay-order-code&quot;&lt;/span&gt;&lt;/span&gt;,
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;token&lt;/span&gt;&quot; : &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;your-token&quot;&lt;/span&gt;&lt;/span&gt;,
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;orderDescription&lt;/span&gt;&quot; : &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;your-order-description&quot;&lt;/span&gt;&lt;/span&gt;,
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;amount&lt;/span&gt;&quot; : &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;number&quot; style=&quot;box-sizing: border-box; color: #009999;&quot;&gt;500&lt;/span&gt;&lt;/span&gt;,
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;currencyCode&lt;/span&gt;&quot; : &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;GBP&quot;&lt;/span&gt;&lt;/span&gt;,
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;customerOrderCode&lt;/span&gt;&quot;:&lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;my-customer-order-code&quot;&lt;/span&gt;&lt;/span&gt;,
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;paymentStatus&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;SUCCESS&quot;&lt;/span&gt;&lt;/span&gt;,
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;paymentResponse&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;{
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;type&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;ObfuscatedCard&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;name&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;expiryMonth&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;number&quot; style=&quot;box-sizing: border-box; color: #009999;&quot;&gt;2&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;expiryYear&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;number&quot; style=&quot;box-sizing: border-box; color: #009999;&quot;&gt;2015&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;cardType&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;VISA_CREDIT&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;maskedCardNumber&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;**** **** **** 1111&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;billingAddress&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;{
            &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;address1&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;18 Linver Road&quot;&lt;/span&gt;&lt;/span&gt;, 
            &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;postalCode&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;SW6 3RB&quot;&lt;/span&gt;&lt;/span&gt;, 
            &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;city&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;London&quot;&lt;/span&gt;&lt;/span&gt;, 
            &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;countryCode&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;GB&quot;&lt;/span&gt;
        }&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;cardSchemeType&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;consumer&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;cardSchemeName&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;VISA CREDIT&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;cardIssuer&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;LLOYDS BANK PLC&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;countryCode&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;GB&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;cardClass&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;credit&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;cardProductTypeDescNonContactless&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;unknown&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;cardProductTypeDescContactless&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;unknown&quot;&lt;/span&gt;&lt;/span&gt;,
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;prepaid&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;false&quot;&lt;/span&gt;
    }&lt;/span&gt;&lt;/span&gt;,
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;shopperEmailAddress&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;name@domain.co.uk&quot;&lt;/span&gt;&lt;/span&gt;,
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;environment&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;TEST&quot;&lt;/span&gt;&lt;/span&gt;,
    &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;riskScore&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;: {
        &quot;&lt;span class=&quot;attribute&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;value&lt;/span&gt;&quot;: &lt;span class=&quot;value&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;string&quot; style=&quot;box-sizing: border-box; color: #219161;&quot;&gt;&quot;1&quot;&lt;/span&gt; 
    }&lt;/span&gt;
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
For more information please visit &lt;a href=&quot;https://online.worldpay.com/docs&quot;&gt;Worldpay online documentation&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Worldpay as a gateway provides various features, (many of which I implemented successfully) like&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Recurring Payments&lt;/li&gt;
&lt;li&gt;Card-on-File (for re-using previously entered card information)&lt;/li&gt;
&lt;li&gt;3d-Secure integration&lt;/li&gt;
&lt;li&gt;Refunds&lt;/li&gt;
&lt;li&gt;Dispute Defence&lt;/li&gt;
&lt;li&gt;Telephone orders&lt;/li&gt;
&lt;li&gt;.. and so on&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Happy integration, people :-)&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/1650896162307006839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/1650896162307006839' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1650896162307006839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1650896162307006839'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2015/08/rest-apis-for-simpler-payment-gateway.html' title='REST APIs for Simpler Payment Gateway Integration into your web and mobile apps'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-4145237915852850334</id><published>2015-04-08T09:42:00.000+05:30</published><updated>2015-04-08T09:42:19.215+05:30</updated><title type='text'>Databases for HA and DR</title><content type='html'>During a recent participation in a bid, responding to an RFP, I had to wear my ops hat and it was a refreshing change, from my dev endeavours in recent past.&lt;br /&gt;
&lt;br /&gt;
One of the things, that I was required to do was to come with a solution that includes HA and DR. When considering the database options for HA and DR, I had to brush up my basics related to database replications, options and also discuss and validate with other senior tech architects who specialize in ops. Following a brief of the learnings that came out of the experience.&lt;br /&gt;
&lt;br /&gt;
To know the basics of replication, the&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Replication_(computing)&quot; target=&quot;_blank&quot;&gt;wikidpedia link for replication&lt;/a&gt; is very good. But first some basics.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Background: why database synchronization is required?&lt;/b&gt;&lt;br /&gt;
Scalability in the middle tier (for example from app servers) is easy to achieve through horizontal scaling, all you would need is mutiple app servers, all symmetrical and fronted by a load balancer.But in the database tier achieving scalability is lot tougher. Especially for data centric applications like OLTP, the database is the single most stressed tier. Though scale-up is an option, it does not provide for a good high availability option. Hence we have to think of 2 or more copies of database, to provide scalability as well as high availability.&lt;br /&gt;
&lt;br /&gt;
Multiple databases can be a tricky option. We can have a cluster of databases all symmetric masters, fronted by a load balancer, but synchronizing data across the databases, is a huge overhead and has potential for failures such as deadlocks, during synchronization.&lt;br /&gt;
&lt;br /&gt;
But to think up other options such a single master, multiple read-only slaves, one must appreciate that, not all data access is equal. If in our application, we can visualize data access as being divided into readonly and readwrite, we may find that only small percentage of application&#39;s data access is read write, say 30%. In such cases having a single master database which caters to read-write and multiple slave databases which cater to read-only can be resorted to.&lt;br /&gt;
&lt;br /&gt;
In any case, having mutiple copies of the database and trying to synchronize data across those databases is something you will have to inevitably deal with, either for database load balancing, high availability(HA) or on a more remote note for disaster recovery (DR).&lt;br /&gt;
&lt;br /&gt;
So what are the options for database synchronization?&lt;br /&gt;
There are 3 broad options for replication:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Storage based replication&lt;/li&gt;
&lt;li&gt;File based replication&lt;/li&gt;
&lt;li&gt;Database replication: this is usually supported natively by the specific database&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Storage based replication&lt;/b&gt;&lt;br /&gt;
Active (real-time) storage replication is usually implemented by distributing updates of a block device to several physical hard disks. This way, any file system supported by the operating system can be replicated without modification, as the file system code works on a level above the block device driver layer. It is implemented either in hardware (in a disk array controller) or in software (in a device driver).&lt;br /&gt;
&lt;br /&gt;
When storage replication is done across locally connected disks it is known as disk mirroring. A replication is extendable across a computer network, so the disks can be located in physically distant locations.&amp;nbsp;For replication, latency is the key factor because it determines either how far apart the sites can be or the type of replication that can be employed.&lt;br /&gt;
&lt;br /&gt;
Basic options here are synchronous replication, which guarantees no data loss at the expense of reduced performance and aysnchronous replication where-in remote storage is updated asynchronously hence it cannot guarantee zero data loss.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;File based replication&lt;/b&gt;&lt;br /&gt;
File-based replication is replicating files at a logical level rather than replicating at the storage block level. There are many different ways of performing this. Unlike with storage-level replication, the solutions almost exclusively rely on software.&lt;br /&gt;
&lt;br /&gt;
File level replication solution yield a few benefits. Firstly because data is captured at a file level it can make an informed decision on whether to replicate based on the location of the file and the type of file. Hence unlike block-level storage replication where a whole volume needs to be replicated, file replication products have the ability to exclude temporary files or parts of a filesystem that hold no business value. This can substantially reduce the amount of data sent from the source machine as well as decrease the storage burden on the destination machine.&lt;br /&gt;
&lt;br /&gt;
On a negative side, as this is a software only solution, it requires implementation and maintenance on the operating system level, and uses some of machine&#39;s processing power (CPU).&lt;br /&gt;
&lt;br /&gt;
File based replication can be done by a kernel driver&amp;nbsp;that intercepts calls to the filesystem functions, filesystem journal replication or batch replication, where-in source and destination file systems are monitored for changes.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Database replication&lt;/b&gt;&lt;br /&gt;
Database replication can be used on many database management systems, usually with a master/slave relationship between the original and the copies. The master logs the updates, which then ripple through to the slaves. The slave acknoledges the updates stating that it has received the update successfully, thus allowing the master, sending (and potentially re-sending until successfully applied) of subsequent updates.&lt;br /&gt;
&lt;br /&gt;
Also database replication becomes difficult when it scales up to support either larger number of databases or increasing distances and latencies between remote slaves.&lt;br /&gt;
&lt;br /&gt;
Some common aspects to consider while choosing database replication:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Do you wish to cater to HA only or you want load balancing as well?&lt;/li&gt;
&lt;li&gt;What is latency for replicaton? Are participant servers in replication, local or remote(site)?&lt;/li&gt;
&lt;li&gt;Are you ready to contend with multiple masters or is single master good enough?&lt;/li&gt;
&lt;li&gt;Can you split your database access into read-write and read-only queries?&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The actual process of database replication usually involves shipping database transaction logs, from master to slave. This shipping can be done as file based transfer of logs or logs can be streamed from master to slaves. Databases can support &quot;specialized transaction logs&quot; which are solely for purposes of replication and are hence optimized.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
If you wish only HA or &amp;nbsp;redundancy, than you can have slave/s in warm standby mode. In this case, master sends all updates to slave but the slave is not used even for read-only access, it is only an up-to-date standby.For HA, using &lt;b&gt;shared storage&lt;/b&gt; for active master and inactive standby can be resorted to. But the shared storage becomes the SPOF(single point of failure).&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
If you intend to have &lt;b&gt;single master and mutiple read-only slaves&lt;/b&gt;, either your application must be smart enough to balance, database access as readwrite connections and read-only connections. Some databases like postgresql provide third party middle-ware libraries which bifurcate client&#39;s database access and send read-write request to master and read-only request balanced across multiple slaves.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
If your application has need to load balance even the read-write requests, then you might think of going in for &lt;b&gt;multiple masters&lt;/b&gt;. Many databases refer to this as database clustering or mutli-master support. Here, read-write commands are sent out to one of the masters and masters are synchronized through mechanisms like 2 phase commits. Multi master replication has challenges such as reduced performance and increased probability of transactional conflicts and related issues like deadlocks.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In addiiton, databases can support features like ability to load balance read-only queries, by allowing &lt;b&gt;parallel execution of single query&lt;/b&gt; across multiple read-only slaves.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Synchronous replication implies, the synchronizations across slaves is guaranteed at the cost of commit performance against the master&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
For DR, remoteness introduces high latency, hence log shipping or async streaming of logs, to a remote warm standby is acceptable.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/4145237915852850334/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/4145237915852850334' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/4145237915852850334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/4145237915852850334'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2015/04/databases-for-ha-and-dr.html' title='Databases for HA and DR'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-5338168027078615767</id><published>2015-03-18T09:57:00.000+05:30</published><updated>2019-12-20T11:41:25.815+05:30</updated><title type='text'>Agile - Tips From Live Projects</title><content type='html'>I recently had a chance to learn about a live agile project as part of agile training programme.&lt;br /&gt;
Below are some of the tips I picked up, while interacting with the key members on the team.&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;The Big Picture&lt;/b&gt;&lt;br /&gt;
The overall release is divided into several phases as mentinoned below.&lt;br /&gt;
Notice the SIT and UAT are run independently, towards end of release.&lt;br /&gt;
This is time consumimg but does reduce risk of any bugs in release.&lt;br /&gt;
This is more relevant for softwares which needs extremely thorough testing.&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Pre foundation Phase (1 week)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Foundation Phase (2 weeks)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Sprint 1 (2 weeks)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Sprint 2&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Sprint 3&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Sprint 4&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Sprint 5
Final / Hardening Sprint&lt;/li&gt;
&lt;li&gt;SIT Test (1 month)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;UAT Test (1 month)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Release&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;
During foundation phase high level estimation done using technique called T-Shirt sizing&lt;br /&gt;
(S, M, L, XL, XXL, XXXL). This helps in deciding scope of sprints.&lt;br /&gt;
&lt;br /&gt;
Plan for sprints to progessively gain velocity&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Balancing RnD and delivery&lt;/b&gt;&lt;br /&gt;
Instead of running 2 week Spikes like Sprints, only Spike Tasks are run to balance RnD efforts with delivering usable functionality.&lt;br /&gt;
&lt;br /&gt;
1 Story = Spike Task1 + Task2 + Task3....&lt;br /&gt;
&lt;br /&gt;
Sprint includes a sensible mix of techincal stories and functional stories.&lt;br /&gt;
Stubs are used for technical components planned for future technical stories.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Estimation&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
Stories estimated as story points using estimation poker&lt;br /&gt;
Task are always estimated / tracked at hours spent.&lt;br /&gt;
There is provision in tool, to estimate task hours and also put in actual hours.&lt;br /&gt;
Over several successive sprints, a good average estimate of 1 Story point = xyz hours crystalizes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Sample Story Status:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
New&lt;br /&gt;
Analyzed &lt;br /&gt;
Approved&lt;br /&gt;
Dev WIP&lt;br /&gt;
Dev Blocked&lt;br /&gt;
Dev Done&lt;br /&gt;
Test WIP&lt;br /&gt;
Test Blocked&lt;br /&gt;
Test Done&lt;br /&gt;
&lt;br /&gt;
Dev Done includes code review&lt;br /&gt;
Test Done includes show-n-tell, given by tester to convince the &amp;nbsp;BA&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Very succint definition of done&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Sample DOD for dev complete:&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Impact Analysis document done&lt;/li&gt;
&lt;li&gt;Code complete&lt;/li&gt;
&lt;li&gt;Code reviewed&lt;/li&gt;
&lt;li&gt;NFR, performance, security tests pass&lt;/li&gt;
&lt;li&gt;Regression tests pass&lt;/li&gt;
&lt;li&gt;All known bugs raised by test team resolved&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;About Code and CI&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Release-wise branch in SVN (version control)&lt;br /&gt;
No branches per sprint&lt;br /&gt;
No parallel sprints&lt;br /&gt;
SVN checkin format:&lt;br /&gt;
&amp;lt;Release&amp;gt;_&amp;lt;Module&amp;gt;_&amp;lt;Story&amp;gt;_&amp;lt;Task/Defect&amp;gt;: Description&lt;br /&gt;
Automated regression testing in place&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Other Takeaways:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
1.&lt;br /&gt;
Very detailed acceptance criteria, Yes No questions, fill blanks, unambigious answers&lt;br /&gt;
Is xxx panel visible as seen in logical diagram? Yes/No&lt;br /&gt;
Does the table/grid contain 13 rows Yes/No&lt;br /&gt;
Quality of story determined by how detailed is acceptance criteria&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;2.&lt;br /&gt;
Story Status like &quot;Test Blocked&quot;, if tester cannot test a story, calls up dev immediately or writes email.&lt;br /&gt;
All Blockers get mentioned in standup&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;3.&lt;br /&gt;
Always testing team is lightly loaded at start of sprint and overloaded towards end of&amp;nbsp;sprint, to reduce this pain&amp;nbsp;point ....&lt;br /&gt;
Have stories at very fine-grained level, eg each story should add up to only few hours of dev task.&lt;br /&gt;
This way, dev always has something testable for tester throughout the sprint
Idle time for testers (waiting for testable functionality) is reduced.







&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/5338168027078615767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/5338168027078615767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/5338168027078615767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/5338168027078615767'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2015/03/agile-tips-from-live-projects.html' title='Agile - Tips From Live Projects'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-3378663665545857959</id><published>2015-02-06T11:08:00.002+05:30</published><updated>2015-02-06T11:16:27.810+05:30</updated><title type='text'>Rapid development of REST webservices with persistence</title><content type='html'>Development of modern business applications, has to become faster and easier, if we are to meet business delivery demands, spanning over ever shorter cycles. Also we are now required to deliver softwares continuosly and incrementally, in an agile manner.&lt;br /&gt;
&lt;br /&gt;
Jump-starting the development process with the right tools and technolgies is the need of the hour.&lt;br /&gt;
&lt;br /&gt;
Rapid development, using currently popular technology, has always been in vogue. Right now exposing middle tier services as REST APIs is all the rage. So how do we develop REST services with persistence, in a rapid manner, with least effort?&lt;br /&gt;
&lt;br /&gt;
I had written an &lt;a href=&quot;http://ganeshghag.blogspot.in/2013/09/grails-23-released-provides-out-of-box.html&quot; target=&quot;_blank&quot;&gt;earlier post on grails 2_3 providing out of box support for REST CRUD&lt;/a&gt;&amp;nbsp;, writing only a simple java bean (DTO), using the grails framework. But that would mean using an entirely new framework like grails only to exploit its REST CRUD functionality. The engineer in me, thought that was an unoptimized use of grails. Why shoudlnt we have this, out of box REST CRUD using spring, hibernate the technologies that we know best already :-)&lt;br /&gt;
&lt;br /&gt;
Well more recently, advancements made in the Spring Data JPA framework, makes it very very easy to develop CRUD REST services out of the box, writing only the entity classes with JPA annotations.&lt;br /&gt;
Well here is how...&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Effectively, we will see, how to write only a simple java bean, annotated with JPA annotations for persistence and using spring data jpa and spring boot, we can automatically generate REST CRUD services for our bean / entity. All this using very little code :-)&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Create a typical maven java project (not a web project)&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
eg. using maven-archetype-quickstart&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;We will use spring boot based spring data jpa and spring data rest&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Use a pom.xml similar to below&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://github.com/ganeshghag/RestSpringDataJpa/blob/master/pom.xml&quot; target=&quot;_blank&quot;&gt;https://github.com/ganeshghag/RestSpringDataJpa/blob/master/pom.xml&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;As per spring data jpa, create persistent entity class say Person as a POJO and annotate it with JPA annotations&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;package com.ghag.rnd.rest.domain;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;import javax.persistence.Entity;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import javax.persistence.GeneratedValue;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import javax.persistence.GenerationType;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import javax.persistence.Id;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;@Entity&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;public class Person {&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;@Id&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;@GeneratedValue(strategy = GenerationType.AUTO)&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;private long id;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;private String firstName;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;private String lastName;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;private String email;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;private String address;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;private String mobile;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;private Integer employeeId;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;//getters and setters go here&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;}&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Again as per spring data jpa framework, create an interface which will tell the spring data jpa framework, to create hibernate jpa based CRUD functionality with respect to the entity class Person we defined above&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;package com.ghag.rnd.rest.repository;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;import java.util.List;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.data.repository.PagingAndSortingRepository;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.data.repository.query.Param;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.data.rest.core.annotation.RepositoryRestResource;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import com.ghag.rnd.rest.domain.Person;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;@RepositoryRestResource(collectionResourceRel = &quot;people&quot;, path = &quot;people&quot;)&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;public interface PersonRepository extends PagingAndSortingRepository&amp;lt;Person, Long&amp;gt; {&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;List&amp;lt;Person&amp;gt; findByLastName(@Param(&quot;name&quot;) String name);&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;}&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
The methods in the interface like findByLastName, impart filtering capability on the the entity queries by entity attributes like lastName.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The annotation below&lt;br /&gt;
&lt;b&gt;@RepositoryRestResource(collectionResourceRel = &quot;people&quot;, path = &quot;people&quot;)&lt;/b&gt;&lt;br /&gt;
ensures that, the CRUD rest services for the Person entity are auto-magically generated for us. This is the main fetaure, I wanted to publicize in this article.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Thats it, now using Spring Boot and its default sensible configurations, you can just right a class similar to below and you should be able to start up the applicatoin with an embedded tomcat server.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;package com.ghag.rnd.rest;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;import org.springframework.boot.SpringApplication;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.context.annotation.ComponentScan;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.context.annotation.Configuration;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.context.annotation.Import;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.data.jpa.repository.config.EnableJpaRepositories;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;@Configuration&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;@EnableJpaRepositories&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;@Import(RepositoryRestMvcConfiguration.class)&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;@EnableAutoConfiguration&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;@ComponentScan &amp;nbsp;//important and required&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;public class Application {&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;public static void main(String[] args) {&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;SpringApplication.run(Application.class, args);&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;}&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;}&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The application will expose the CRUD REST services for persistent entity Person at&lt;br /&gt;
http://server:port/people&lt;br /&gt;
&lt;br /&gt;
you can easily test the services using curl commands like following:&lt;br /&gt;
curl -i -X POST -H &quot;Content-Type:application/json&quot; -d @insert.cmd http://localhost:8080/people&lt;br /&gt;
where file insert.cmd contains json for the Person object like thus:&lt;br /&gt;
{ &lt;br /&gt;
&quot;firstName&quot; : &quot;Ganesh&quot;, &lt;br /&gt;
&quot;lastName&quot; : &quot;Ghag&quot;,&lt;br /&gt;
&quot;email&quot;:&quot;some@some.com&quot;,&lt;br /&gt;
&quot;address&quot;:&quot;flower valley, thane&quot;,&lt;br /&gt;
&quot;mobile&quot;:&quot;3662626262&quot;,&lt;br /&gt;
&quot;employeeId&quot;:8373&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;In order to customize the application, writing custom REST controllers is as easy as writing below POJO&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;package com.ghag.rnd.rest.controllers;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;import org.springframework.beans.factory.annotation.Autowired;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.web.bind.annotation.PathVariable;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.web.bind.annotation.RequestMapping;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.web.bind.annotation.RequestMethod;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;import org.springframework.web.bind.annotation.RestController;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;import com.ghag.rnd.rest.repository.PersonRepository;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;@RestController&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;@RequestMapping(&quot;/custom&quot;)&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;public class MyCustomController {&lt;/i&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;i&gt; &lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;@Autowired&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;PersonRepository personRepository;&lt;/i&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;i&gt; &lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;@RequestMapping(value=&quot;/sayHello/{input}&quot;, method=RequestMethod.GET)&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;public String sayHello(@PathVariable String input){&lt;/i&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;i&gt;  &lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;System.out.println(&quot;findall=&quot;+personRepository.findAll());&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;personRepository.deleteAll();&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;return &quot;Hello!&quot;+input;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;}&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;}&lt;/i&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;b&gt;To further enhance the CRUD application, we can easily&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;use above application as a microservice, using spring boot as is&lt;/li&gt;
&lt;li&gt;export above application as a war and deploy it on traditional app server&lt;/li&gt;
&lt;li&gt;use various logging for debugging&lt;/li&gt;
&lt;li&gt;use spring based validations&lt;/li&gt;
&lt;li&gt;use spring security&lt;/li&gt;
&lt;li&gt;switch CRUD database from current default H2 to any of our choice using spring boot config file application.properties&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
Please refer spring boot documentation for accomplishing the above mentioned enhancments.&lt;br /&gt;
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/&lt;br /&gt;
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
By using hibernate tools reverse engineering, given an existing database, auto-generating JPA annotated entities is a no-brainer and with the above knowledge of generating REST CRUD services, it means, you can expose a database, as &amp;nbsp;REST services, with less than a days work.</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/3378663665545857959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/3378663665545857959' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/3378663665545857959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/3378663665545857959'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2015/02/rapid-development-of-rest-webservices.html' title='Rapid development of REST webservices with persistence'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-403608348334649453</id><published>2014-09-08T14:17:00.001+05:30</published><updated>2014-09-09T09:52:07.988+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="hibernate"/><category scheme="http://www.blogger.com/atom/ns#" term="multi-tenant"/><title type='text'>Database multi-tenancy using Hibernate 4</title><content type='html'>With many business applications being written, with intent to be deployed on cloud, there is increasingly a need to design multi-tenancy into your application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For persistence layer multi-tenant design offers a few options:&lt;br /&gt;
&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/aa479086.aspx&quot;&gt;http://msdn.microsoft.com/en-us/library/aa479086.aspx&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;separate database per tenant&lt;/li&gt;
&lt;li&gt;separate schema, same database per tenant&lt;/li&gt;
&lt;li&gt;same schema, same database for all tenant with discriminator column for tenant rows in same table&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;
In this article, I am going to talk more about implementing the options 1 and 2 using the support in hibernate 4, for multi-tenancy.&lt;br /&gt;
&lt;br /&gt;
Also for the database connections, we have choice of having a common database connection pool, from which connections are allocated to each tenant request, or separate connection pools for each tenant.&lt;br /&gt;
For the common connection pool approach, each connection before being used for data access, needs to be &quot;primed&quot; for usage against a tenant database or schema, using statements like &quot;use &amp;lt;tenant_schema&amp;gt;&quot; or &quot;use &amp;lt;tenant_database&amp;gt;&quot;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
Multi-tenancy in Hibernate&lt;/h3&gt;
&lt;br /&gt;
&lt;b&gt;For the &quot;separate connection pool per tenant approach&quot;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;First we need to implement a custom connection provider as follows&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbcp2.BasicDataSource;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;

public class ConnectionProviderImpl implements ConnectionProvider {
 
 private final BasicDataSource basicDataSource = new BasicDataSource();
 
 public ConnectionProviderImpl(String database){&lt;/pre&gt;
&lt;pre class=&quot;brush: java&quot;&gt;                //this should be read from properties file
  basicDataSource.setDriverClassName(&quot;com.mysql.jdbc.Driver&quot;);
  basicDataSource.setUrl(&quot;jdbc:mysql://localhost:3306/&quot;+database);
  basicDataSource.setUsername(&quot;myuser&quot;);
  basicDataSource.setPassword(&quot;mypassword&quot;);
  basicDataSource.setInitialSize(2);
  basicDataSource.setMaxTotal(10);
 }

 @Override
 public boolean isUnwrappableAs(Class arg0) {
  return false;
 }

 @Override
 public &lt;t&gt; T unwrap(Class&lt;t&gt; arg0) {
  return null;
 }

 @Override
 public void closeConnection(Connection arg0) throws SQLException {
  arg0.close();
 }

 @Override
 public Connection getConnection() throws SQLException {
  return basicDataSource.getConnection();
 }

 @Override
 public boolean supportsAggressiveRelease() {
  return false;
 }

}


&lt;/t&gt;&lt;/t&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Next we need to implement&amp;nbsp;AbstractMultiTenantConnectionProvider of hibernate, as follows&lt;/b&gt;&lt;br /&gt;
Here I am maintaining a map of database identifiers against, connection providers.&lt;br /&gt;
When hibernate invokes the selectConnectionProvider( ) method with the tenant identifier, we use the tenant identifier to return the &quot;appropriate&quot; connection provider from the map.&lt;br /&gt;
It is necessary to implement a method like getAnyConnectionProvider( ), which should return, a sensible - default connection provider.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;

public class MultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider {
 
 private HashMap&lt;string connectionprovider=&quot;&quot;&gt; connProviderMap = new HashMap&lt;string connectionprovider=&quot;&quot;&gt;();
 
 public MultiTenantConnectionProvider(){
  

  List&lt;string&gt; providerNames = new ArrayList&lt;string&gt;();
  providerNames.add(&quot;default_db&quot;);
  providerNames.add(&quot;db1&quot;);
  providerNames.add(&quot;db2&quot;);
  //need to get above from properties file
  
    for (String providerName : providerNames) {
       connProviderMap.put(providerName, new ConnectionProviderImpl(providerName));
    }
  
 }
 
 @Override
 protected ConnectionProvider getAnyConnectionProvider() {
  System.out.println(&quot;inside MultiTenantConnectionProvider::getAnyConnectionProvider&quot;);
  return connProviderMap.get(&quot;default_db&quot;);
 }

 @Override
 protected ConnectionProvider selectConnectionProvider(String tenantId) {
  ConnectionProvider connectionProvider = connProviderMap.get(tenantId);
  if(connectionProvider == null)
   connectionProvider =  new ConnectionProviderImpl(&quot;default_db&quot;);
  
  return connectionProvider;
 } 

}


&lt;/string&gt;&lt;/string&gt;&lt;/string&gt;&lt;/string&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;For common connection pool for all tenants.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;We need to implement&amp;nbsp;&lt;/b&gt;&lt;span style=&quot;background-color: white; font-family: Consolas, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, Courier, monospace; font-size: 15.5555562973022px; line-height: 17.6000003814697px;&quot;&gt;MultiTenantConnectionProvider&amp;nbsp;&lt;/span&gt;&lt;b&gt;of hibernate, as follows&lt;/b&gt;&lt;br /&gt;
Since we are using the same connection pool, in getConnection(), we need to prime the connection using a SQL statement like &#39;use &amp;lt;database&amp;gt;&#39;, so that the connection&#39;s further use will be in database as per tenant_id.&lt;br /&gt;
Also in releaseConnection( ), we have a &#39;use &amp;lt;default_db&amp;gt;&#39; as a fallback.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;import java.sql.Connection;
import java.sql.SQLException;

import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;

public class MultiTenantConnectionProviderWithSingleDBPool implements
  MultiTenantConnectionProvider {
 
 private final ConnectionProvider connectionProvider = new ConnectionProviderImpl(CurrentTenantIdentifierResolver.DEFAULT_TENANT_ID); 
 

 @Override
 public boolean isUnwrappableAs(Class arg0) {
  return false;
 }

 @Override
 public &lt;t&gt; T unwrap(Class&lt;t&gt; arg0) {
  return null;
 }

 @Override
 public Connection getAnyConnection() throws SQLException {
  System.out.println(&quot;inside MultiTenantConnectionProvider::getAnyConnection&quot;);
  return connectionProvider.getConnection();
 }

 @Override
 public void releaseAnyConnection(Connection connection) throws SQLException {
  connectionProvider.closeConnection( connection );
 }

 @Override
 public Connection getConnection(String tenantIdentifier) throws SQLException {
  final Connection connection = getAnyConnection();
  try {
     connection.createStatement().execute( &quot;USE &quot; + tenantIdentifier );
  }
  catch ( SQLException e ) {
     throw new HibernateException(
       &quot;MultiTenantConnectionProvider::Could not alter JDBC connection to specified schema [&quot; +tenantIdentifier + &quot;]&quot;,e);
  }
  return connection;
 }

 @Override
 public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
  try {
   connection.createStatement().execute( &quot;USE default_db&quot; );
  }
  catch ( SQLException e ) {
     throw new HibernateException(
     &quot;Could not alter JDBC connection to specified schema [&quot; +
   tenantIdentifier + &quot;]&quot;,e);
  }
  connectionProvider.closeConnection( connection );
 }

 @Override
 public boolean supportsAggressiveRelease() {
  return false;
 }

}



&lt;/t&gt;&lt;/t&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
refer hibernate docs&lt;br /&gt;
&lt;a href=&quot;http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch16.html&quot;&gt;http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch16.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, to persuade hibernate to use tenant identifier before any database access, we can&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;manually set the tenant identifier on hibernate session factory&lt;/li&gt;
&lt;li&gt;we can implement hibernate tenant identifier resolver&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Manually set the tenant identifier on hibernate session factory&lt;/b&gt;&lt;br /&gt;
This can be done, in a web application in any suitable interceptor where hibernate session is available&lt;br /&gt;
&lt;div&gt;
&lt;div class=&quot;example-contents&quot;&gt;
&lt;pre class=&quot;&quot; style=&quot;background-color: whitesmoke; border: 1px solid rgb(204, 204, 204); font-family: Monaco, monospace; font-size: 0.9em; line-height: 1.29em; overflow: auto; padding: 5px 15px 5px 25px;&quot; xmlns:d=&quot;http://docbook.org/ns/docbook&quot; xmlns:rf=&quot;java:org.jboss.highlight.XhtmlRendererFactory&quot; xmlns=&quot;&quot;&gt;Session session = sessionFactory.withOptions()
        .tenantIdentifier( yourTenantIdentifier )
        ...
        .openSession();&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Hibernate tenant identifier resolver can be implemented as follows.&lt;br /&gt;
Here I am using a ThreadLocal to get the tenant identifier. The threadlocal itself can be set early on in the http request thread in say, a servlet filter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;import org.hibernate.context.spi.CurrentTenantIdentifierResolver;

public class CurrentTenantIdentifierResolver implements
  CurrentTenantIdentifierResolver {
 
 public static ThreadLocal&lt;string&gt; _tenantIdentifier = new ThreadLocal&lt;string&gt;();
 public static String DEFAULT_TENANT_ID = &quot;default_db&quot;;

 @Override
 public String resolveCurrentTenantIdentifier() {
  System.out.println(&quot;from inside resolveCurrentTenantIdentifier....&quot;);
  String tenantId = _tenantIdentifier.get();
  if(tenantId == null)
   tenantId = DEFAULT_TENANT_ID;
  
  System.out.println(&quot;threadlocal tenant id =&quot;+tenantId);
  return tenantId;
 }

 @Override
 public boolean validateExistingCurrentSessions() {
  return true;
 }

}



&lt;/string&gt;&lt;/string&gt;&lt;/pre&gt;
&lt;div&gt;
Finally, the hibernate configuration for specifying that we are using hibernate mutli-tenancy, in hibernate.cfg.xml&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;textarea cols=&quot;70&quot; rows=&quot;10&quot;&gt;&lt;property name=&quot;hibernate.multiTenancy&quot;&gt;DATABASE&lt;/property&gt;

&lt;property name=&quot;hibernate.multi_tenant_connection_provider&quot;&gt;
com.some.MyMultiTenantConnectionProvider
&lt;/property&gt;

&lt;property name=&quot;hibernate.tenant_identifier_resolver&quot;&gt;
com.some.MyCurrentTenantIdentifierResolver
&lt;/property&gt;
&lt;/textarea&gt;

&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
That&#39;s it people,&lt;br /&gt;
Happy multi-tenanting :-)&lt;br /&gt;
&lt;br /&gt;
Cheers!&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/403608348334649453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/403608348334649453' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/403608348334649453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/403608348334649453'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2014/09/database-multi-tenancy-using-hibernate-4.html' title='Database multi-tenancy using Hibernate 4'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-1590246821149138153</id><published>2014-04-17T12:28:00.002+05:30</published><updated>2015-04-10T15:54:42.841+05:30</updated><title type='text'>Using free openshift java PAAS, to run a web application on an online version of tomcat</title><content type='html'>Many times you have a war file, that you would like to deploy such that the application becomes available online.A classical use case is using a REST service as stub for your mobile app or thin client web app.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://www.openshift.com/get-started&quot; target=&quot;_blank&quot;&gt;Openshift online PAAS&lt;/a&gt; is an easy solution for such free hotsitng of a java web application&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;Create a free account at &lt;a href=&quot;https://openshift.redhat.com/app/console/applications&quot; target=&quot;_blank&quot;&gt;open shift online&lt;/a&gt;&amp;nbsp;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;Download their rhc command line tool&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
Fire following command to create 1 of 3 free apps, where name of new hosted web app is for example say, restgrails&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;rhc create-app restgrails tomcat-7&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Go to the &lt;a href=&quot;https://openshift.redhat.com/app/console/applications&quot; target=&quot;_blank&quot;&gt;open shift web console&lt;/a&gt;&amp;nbsp;and note down the ssh url of the git repository&lt;br /&gt;
setup ssh keys for the open shift git repo using command&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;rhc setup&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;If required, place the keys generated in &amp;lt;user-dir&amp;gt;\.ssh into &amp;lt;git-install-dir&amp;gt;\.ssh&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
fire following command on your local machine&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;git clone &amp;lt;git_url&amp;gt; restgrails&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
on your local machine the above git command will create a new directory called restgrails and checkout default web app from openshift git repo to your local machine&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;cd restgrails&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Fire following commands to get rid of the default web app&#39;s src and pom.xml, since we will deploy a ready made war file onto the openshift PAAS&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;git rm -rf src/ pom.xml&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/b&gt;
&lt;b&gt;&lt;i&gt;git commit -am &quot;deleted default source code&quot;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Now prepare the ready made war file for deploying onto open shift&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;copy war file to restgrails/webapps/&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;rename war file to ROOT.war &amp;nbsp;--this is important if you want to map your webapp to the openshift online app URL&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;git add .&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;git commit -am &quot;added new root.war to webapps&quot;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;git push --force&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Above git push command, will trigger a deploy of the war file into the remote tomcat on open shift and soon the web app will become available online as say&lt;br /&gt;
&lt;br /&gt;
http://restgrails-ideafountain.rhcloud.com/&lt;br /&gt;
ie&lt;br /&gt;
http://&amp;lt;web-app-name&amp;gt;-&amp;lt;domain-name-reg-with-openshift-online&amp;gt;.rhcloud.com/&lt;br /&gt;
&lt;br /&gt;
you can tail the tomcat server logs with the following command&lt;br /&gt;
&lt;b&gt;&lt;i&gt;rhc tail restgrails&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/b&gt;
For databases, openshift online does support databases like mongodb, mysql and postgresql, so if your app uses hibernate, it can easily be configured to use online database like say mysql or postgresql, while running it online&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;to check logs&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
Go to openshift web console, and &lt;b&gt;click on Remote access,
want to login to your application&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: #1f497d;&quot;&gt;Fire ssh command, in textbox on
web console, from your dos prompt&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: #1f497d;&quot;&gt;Example:&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;ssh &lt;a href=&quot;mailto:54afae4d5973cad4bd000092@plateletdonation-ideafountain.rhcloud.com&quot;&gt;acvahdvahdvah@plateletdonation-ideafountain.rhcloud.com&lt;/a&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: #1f497d;&quot;&gt;You will be get logged-in to the
VM.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: #1f497d;&quot;&gt;Here give following commands:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: #1f497d;&quot;&gt;[plateletdonation-ideafountain.rhcloud.com ]\&amp;gt; find &amp;nbsp;. -name *.log&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: #1f497d;&quot;&gt;find: `./.tmp&#39;: Permission
denied&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: #1f497d;&quot;&gt;find: `./.sandbox&#39;: Permission
denied&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: #1f497d;&quot;&gt;find: `./.ssh&#39;: Permission
denied&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;b&gt;&lt;span style=&quot;color: #1f497d;&quot;&gt;./app-root/logs/jbossews.log&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;b&gt;&lt;span style=&quot;color: #1f497d;&quot;&gt;./jbossews/tmp/stacktrace.log&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: #1f497d;&quot;&gt;[plateletdonation-ideafountain.rhcloud.com ]\&amp;gt; tail -f ./app-root/logs/jbossews.log&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/1590246821149138153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/1590246821149138153' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1590246821149138153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1590246821149138153'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2014/04/using-free-openshift-java-paas-to-run.html' title='Using free openshift java PAAS, to run a web application on an online version of tomcat'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-4703584444296640861</id><published>2014-03-26T15:58:00.001+05:30</published><updated>2014-03-26T16:02:06.829+05:30</updated><title type='text'>Why is enterprise application development different from just programming?</title><content type='html'>&lt;i&gt;&lt;b&gt;Any monkey can write code that works!&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
Writing code that fulfills a functionality is a very important first step in the process of developing an enterprise application, but it is only the beginning, the enterprise application is far from done...&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;So what else is involved in developing an enterprise application?&lt;/b&gt;&lt;br /&gt;
As it turns out there are several other aspects of development that have to be considered:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Is the code unit tested with sufficient test coverage?&lt;/li&gt;
&lt;li&gt;Is the code thread safe, in the face of multiple users accessing it?&lt;/li&gt;
&lt;li&gt;Is the code transactional?&lt;/li&gt;
&lt;li&gt;Is the code secure?&lt;/li&gt;
&lt;li&gt;Is the code easy to debug? Is it instrumented with logging at appropriate levels?&lt;/li&gt;
&lt;li&gt;Does the code handle exceptions and errors?&lt;/li&gt;
&lt;li&gt;Is the code optimized for performance and for memory consumption?&lt;/li&gt;
&lt;li&gt;Is the code resilient? Can it recover, from a failure?&lt;/li&gt;
&lt;li&gt;Is the code easily extensible and maintainable?&lt;/li&gt;
&lt;li&gt;Is the code portable across deployment environments?&lt;/li&gt;
&lt;li&gt;Are all the configurable properties externalized and easily changed during deployment?&lt;/li&gt;
&lt;li&gt;Is the code able to inter-operate with legacy systems to be integrated?&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Answering all the above questions to the satisfaction of the non-functional requirements, is equally important. Many developers are aware of all the above aspects of development but completely ignore them, when asked about estimates when they think they can complete a particular functionality or feature of the enterprise application under development :-(&lt;br /&gt;
&lt;br /&gt;
On a side note, even when we as developers decide to write our own reusable component or framework, please take into consideration that all the above aspects need to be built into the component/framework and hence many times it makes better sense to use an opensource component which is popular used or has withstood the test of time.Don&#39;t re-invent the wheel :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Taking an application from developers machine to production&lt;/b&gt;&lt;br /&gt;
Taking a functionally complete application from a developers machine upto production is a long walk. Lets see some of the common things that need to be done:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;automated integration tests especially for regression testing&lt;/li&gt;
&lt;li&gt;scripts for automated checkout, packaging and deployment&lt;/li&gt;
&lt;li&gt;automated configuration of application &amp;nbsp;as per environment eg. integration, qc, uat and prod&lt;/li&gt;
&lt;li&gt;scripts for application life cycle management - start, restart, stop, application&lt;/li&gt;
&lt;li&gt;scripts/tools for application database cleanup and archival&lt;/li&gt;
&lt;li&gt;scripts/tools for application log files cleanup and archival&lt;/li&gt;
&lt;li&gt;scripts/tools for monitoring application health and sending alerts&lt;/li&gt;
&lt;li&gt;scripts/tools for scrapping application logs for exceptions, etc and sending out alerts&lt;/li&gt;
&lt;li&gt;scripts/tools for performance and memory monitoring of application&lt;/li&gt;
&lt;li&gt;migrating existing database to new application database + testing app against migrated data&lt;/li&gt;
&lt;li&gt;scripts for scheduling house keeping work around the application&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
As can be easily seen, there is a very substantial and important component of &quot;operations&quot; which needs to be undertaken, for successful implementation of any application. All these activities can hardly be classified as typical coding. These need to be factored into time estimates as well as workforce planning&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/4703584444296640861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/4703584444296640861' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/4703584444296640861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/4703584444296640861'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2014/03/why-is-enterprise-applicaton.html' title='Why is enterprise application development different from just programming?'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-1782222472880627</id><published>2014-03-25T14:40:00.002+05:30</published><updated>2014-03-26T13:52:57.627+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="express.js"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="node.js"/><category scheme="http://www.blogger.com/atom/ns#" term="reactive frameworks"/><title type='text'>When and why to use NODE.JS</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;iframe allowfullscreen=&#39;allowfullscreen&#39; webkitallowfullscreen=&#39;webkitallowfullscreen&#39; mozallowfullscreen=&#39;mozallowfullscreen&#39; width=&#39;320&#39; height=&#39;266&#39; src=&#39;https://www.youtube.com/embed/zN5ukaO3wqg?feature=player_embedded&#39; frameborder=&#39;0&#39;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;b&gt;Node.js !&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
The new kid on the block, has definitely been turning main stream. So, you must have heard buzzwords like async io, server side javascript, etc getting associated with the node hype. Some remarks from the sceptics as well - you cant handle dynamic javascript with your immature development workforce or node.js is ok for hello-world apps but not necessarily for primetime on the enterprise applications landscape.&lt;br /&gt;
&lt;br /&gt;
Well heres my attempt clearing up the mist, with regards to node.js and related frameworks...&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;When to use Node.js&lt;/b&gt;&lt;/h3&gt;
As very rightly pointed out by the authors of node.js, it is an excellent fit for &lt;i&gt;DIRT-y&lt;/i&gt; applications. DIRT stands for &lt;b&gt;&lt;i&gt;Data Intensive, Real Time&lt;/i&gt;&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;How do Java EE web apps work&lt;/b&gt;&lt;/h3&gt;
Lets start out with a traditional Java EE web applications hosted on say a tomcat container, when a 1000 users concurrently access the web application, for each user request a thread is spawned by the web container. Each thread, does processing, passing control through, various application layers like view, controller, service, data access to finally hit a database or backend, get the relevant data and bring it back to presentation tier from where it may be formatted like an html response and sent back to the client browser as an Http response. The hundreds/thousands of threads running in the web container, ensure scalability of the application. But each thread contains synchronous method calls. Each thread is held up, while the sync call completes.The best to emphasize this is through a database call such as&lt;br /&gt;
ResultData data = personDao.updatePersonDetails(person);&lt;br /&gt;
&amp;nbsp;( above call blocks till all DB rows are fetched )&lt;br /&gt;
&lt;br /&gt;
it is not uncommon for many threads in such an application to be waiting for IO either disk io or network io (as in a database call). As a result one can clearly observe that hardly 10%-20% of cpu is utilized on the web tier, most latency is due to threads waiting on IO.&lt;br /&gt;
&lt;br /&gt;
Can the above latency be reduced?&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;Enter Node.js with its aysnc io&lt;/b&gt;&lt;/h3&gt;
Node.js at its simplest and most fundamental level prefers non-blocking function calls, through incessant use of callbacks. For example the above blocking database call can be simplified logically to the following async call:&lt;br /&gt;
personDao.updatePersonDetails(person, function(err, numRowsAffected ){....} );&lt;br /&gt;
Above call issues request to database driver for update but does not wait for results, it continues to next line of execution, and when the database update has been made, the callback i.e. the anonymous functiona gets executed, returning back the error if any and the number of rows affected by the updated.&lt;br /&gt;
&lt;br /&gt;
Though the above difference between using sync blocking functions v/s using async functions with callbacks may seem trivial, if we adopt the async non-blocking function calling as the default way of programming soon things start adding up.&lt;br /&gt;
&lt;br /&gt;
Instead of having 1 thread dedicated for an http request and having thousands of such threads, in node.js we have async functions, which do processing in bits and dont hold up a single thread. The node.js model starts exhibiting more scalability, due to non-blocking nature of calls in the processing stack.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;Where are the benchmarks?&lt;/b&gt;&lt;/h3&gt;
Well, consider this, apache webserver uses the multi threaded model whereas nginx uses non-blocking IO, it has been proven several benchmarks that nginx with its non-blocking io shows roughly 20% better scalability than apache webserver. So even for serving static content, we know, async io is always going to be more scalable.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;Can Node.js leverage multiple cores? Is it fault tolerant?&lt;/b&gt;&lt;/h3&gt;
This was another valid criticism raised against node,js platform in early days of the framework. We need to understand that node.js server has only a single thread available for the application&#39; usage (there may be others for doing the server&#39;s internal housekeeping). Due to the above limitation, node.js processing runs on a single core and is also susceptible to outage since one thread crashing can bring processing down for all clients. Thankfully multiple node.js servers can be run on the same machine with a load balancer upfront. Or node.js modules like &quot;cluster&quot;, &quot;upstart&quot; and &quot;forever&quot; ensure, node.js servers can be horizontally scaled and will have features like guaranteed uptime and automatic restarts, on crash.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;Node.js for realtime apps&lt;/b&gt;&lt;/h3&gt;
Out of the acronym DIRT, we already saw how node.js is a good fit for &quot;data intensive&quot; applications, well its time to talk about one more category of applications, namely &quot;realtime applications&quot; for which node.js would be suitable.&lt;br /&gt;
Again lets consider, traditional web apps, which require to show data that changes frequently at the backend. The traditional approach using Http is for browser based javascript clients to &quot;poll&quot; the server using &quot;auto-refresh&quot; tags. This approach apart from loading up the server is also very unoptimized, instead newer full-duplex protocols like websocket, can be used by the servers to push content, messages, notifications to the client browsers, &quot;whenever&quot; the server events occur.&lt;br /&gt;
&lt;br /&gt;
This event driven approach, to pushing from server to client is very compatible with node.js async and non-blocking APIs, hence there is excellent support in node.js based modules like socket.io, for server push. This makes node.js very suitable for web applications that require high interactivity, server push and notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;What is node.js and how useful is it to build real life web apps from scratch?&lt;/b&gt;&lt;/h3&gt;
Well node.js core is really a http server and a platform for hosting web apps. The core node.js hence does not include any features which directly are used in the making of a web application. To create a real life web application, one needs a framework with many features like ability to host static content from the server&#39;s native file system, user authentication, session and cookie management, templatable views, nagivation and routing framework, binding model and views, error handling, request body parsing etc.&lt;br /&gt;
For providing all above functionalities the core node.js needs to have relevant modules added on top of it&lt;br /&gt;
Node.js provides a robust module system called npm stands for Node package manager, which helps in installing such node.js modules.&lt;br /&gt;
The most critical module which provides pluggable &lt;b&gt;middle-ware &lt;/b&gt;is a module called &lt;b&gt;connect&lt;/b&gt;.&lt;br /&gt;
On top of connect is a module called &lt;b&gt;express.js&lt;/b&gt; which provides a full fledged web application framework.&lt;br /&gt;
More custom requirements for the web app can be fulfilled by installing appropriate modules freely available via the npm (node package manager).&lt;br /&gt;
Similarly, &lt;b&gt;templating engines like jade and ejs&lt;/b&gt; can be plugged into frameworks like express.js, thereby enriching the node.js ecosystem for your web application development.&lt;br /&gt;
&lt;br /&gt;
In subsequent articles, I will be walking through developing a basic node.js web application for doing CRUD (create, read, update, delete) into a mongo database. You will be pleasantly surprised how easy and elegant it is to develop web applications in node.js based frameworks.&lt;br /&gt;
&lt;br /&gt;
Cheers!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/1782222472880627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/1782222472880627' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1782222472880627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1782222472880627'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2014/03/when-and-why-to-use-nodejs.html' title='When and why to use NODE.JS'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-4276539334906649241</id><published>2014-03-10T09:45:00.001+05:30</published><updated>2014-03-10T09:45:39.387+05:30</updated><title type='text'>How to build a cross platform mobile app using only a browser</title><content type='html'>&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;344&quot; src=&quot;//www.youtube.com/embed/AQIgX49HRqo&quot; width=&quot;459&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/4276539334906649241/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/4276539334906649241' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/4276539334906649241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/4276539334906649241'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2014/03/how-to-build-cross-platform-mobile-app.html' title='How to build a cross platform mobile app using only a browser'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-1173062980839427002</id><published>2014-02-07T11:08:00.002+05:30</published><updated>2014-02-10T17:18:45.886+05:30</updated><title type='text'>Securing your REST API</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1QdeljOzvtbnL-mVWBo5CQi4wDygzJExOjsF-reEM28ksU3ptF1mN5jF2FvbOkqrOwqdONLv523vCRlpo0Nu6kqZtujSKE1v9o9icouhrTB4Wh-l-I6jJKN3Huv_hfP7tpO-k66hddgr_/s1600/sec2.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1QdeljOzvtbnL-mVWBo5CQi4wDygzJExOjsF-reEM28ksU3ptF1mN5jF2FvbOkqrOwqdONLv523vCRlpo0Nu6kqZtujSKE1v9o9icouhrTB4Wh-l-I6jJKN3Huv_hfP7tpO-k66hddgr_/s1600/sec2.jpg&quot; height=&quot;344&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
With developers exposing application functionality as REST services, willy nilly all over the enterprise, the onus of securing these REST services is on them as well. Here I will discuss the options for means of authenticating your REST services. For authenticating REST services you have the following broad options:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Use HTTP Basic Auth, Digest, Form based or Client Certificates&lt;/li&gt;
&lt;li&gt;Use custom token based authentication mechanisms&lt;/li&gt;
&lt;li&gt;Use OAuth 2.0 - Two legged or Three Legged Auth&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Using HTTP Basic Auth, Digest, Form based or Client Certificates&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;
Since HTTP is the most popular implementation of REST, Java EE based authentication mechanisms hold true for REST service calls as well. Here we have 3 options, as mentioned well in Java EE Security documentation.&lt;br /&gt;
&lt;br /&gt;
To secure REST API exposed at http://&amp;lt;hostname&amp;gt;:&amp;lt;portnumber&amp;gt;/web-app-context/webapi/rest-resource we will use the following configuration in web application&#39;s web.xml&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;textarea cols=&quot;80&quot; readonly=&quot;true&quot; rows=&quot;20&quot;&gt; 
&lt;security-role&gt;
  &lt;role-name&gt;admin&lt;/role-name&gt;
&lt;/security-role&gt;

&lt;security-constraint&gt;
  &lt;display-name&gt;SecurityConstraint1&lt;/display-name&gt;
  &lt;web-resource-collection&gt;
   &lt;web-resource-name&gt;WRCollection&lt;/web-resource-name&gt;
   &lt;url-pattern&gt;/webapi/*&lt;/url-pattern&gt;
  &lt;/web-resource-collection&gt;
  &lt;auth-constraint&gt;
   &lt;role-name&gt;admin&lt;/role-name&gt;
  &lt;/auth-constraint&gt;
&lt;/security-constraint&gt;
&lt;login-config&gt;
  &lt;auth-method&gt;BASIC&lt;/auth-method&gt;
&lt;/login-config&gt;

&lt;/textarea&gt;
&lt;br /&gt;
&lt;br /&gt;
Above, configuration uses the &quot;Basic Auth&quot; scheme, similarly REST based (logical) resources, can be secured using DIGEST, Form Based and client-certificates schemes as well. Please refer &lt;a href=&quot;http://docs.oracle.com/javaee/5/tutorial/doc/bncbe.html#bncbn&quot; target=&quot;_blank&quot;&gt;Java EE security documentation &lt;/a&gt;for further details.&lt;br /&gt;
&lt;br /&gt;
Also, suitable realm can be used to refer to credential stores. If you want to make the actual authentication to be portable across application servers you can use JAAS and write-up your own custom LoginModule and CallbackHandler.&lt;br /&gt;
&lt;br /&gt;
So far so good, securing REST services is like any conventional Java EE web application. But....&lt;br /&gt;
&lt;br /&gt;
Many times, the REST services are consumed by not conventional browser based UIs, but rather by mobile applications based on say android or iOS. In such cases, having a mobile app which needs a re-login after &amp;nbsp;HttpSession timeout of say 30 minutes(for tomcat), can be very tedious and undesirable. Instead most mobile apps allow user to enter the username and password, once and then store it on the mobile device as an app preference.&lt;br /&gt;
&lt;br /&gt;
In order to provide a feature such as above, with mobile clients in mind, we can use &quot;custom tokens with expirations&quot;. The idea itself is quite simple.&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;The first time a mobile user uses the app, he is asked for a username and password for authentication.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;This server backend provides a REST API such as /login which takes a Http POST and username and password as part of Http request body.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;The password itself can be sent across using encoding such as base-64 (over SSL obviously!)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;The server validates the username and password going against a credential store such as LDAP based or ActiveDirectory based. Once the user is authenticated, a unique token is generated by server, the server saves this token against the username, along with say a timestamp and expiry date time and also the token is sent back to the client.&lt;/li&gt;
&lt;li&gt;The client stores this token say in HTML5 localstorage and uses it in subsequent REST requests, in a custom http header&lt;/li&gt;
&lt;li&gt;For subsequent requests, the server looks at the custom header retrieves the token, validates that it is valid by checking against the username and also ascertaining that it has not expired as per expiry policy.&lt;/li&gt;
&lt;li&gt;If token is valid, the request goes through, if token is invalid or expired, the server throws back a 401 error, which makes the client go back to login page for re-login&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
The above mechanism is depicted in representative code below, to clarify the explanation.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The server side authentication and token check can be done using, a servlet filter interceptor as depicted below:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;brush: java&quot;&gt;package com.mastek.opensource.security.filters;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SecurityTokenFilter implements Filter {
 
 @Override
 public void doFilter(ServletRequest req, ServletResponse resp, 
   FilterChain chain) throws IOException, ServletException {
  
  HttpServletRequest request = (HttpServletRequest)req;
  String token = request.getHeader(&quot;MyTokenField&quot;);
  
  //additionally check if the token is valid
  //valid can also check if token is expired as per policy
  if(token == null || token.length() == 0)  
     //send HTTP resp code 401: Unauthorized
     ((HttpServletResponse)resp).setStatus(HttpServletResponse.SC_UNAUTHORIZED); 
  else
     chain.doFilter(req, resp);
  
 }


 @Override
 public void destroy() {

 }
 
 @Override
 public void init(FilterConfig arg0) throws ServletException {

 }
 
}


&lt;/pre&gt;
The servlet filter entry in web.xml is shown below:

&lt;textarea cols=&quot;80&quot; readonly=&quot;true&quot; rows=&quot;9&quot;&gt; 
&lt;filter&gt;
  &lt;filter-name&gt;SecurityTokenFilter&lt;/filter-name&gt;
  &lt;filter-class&gt;your.package.SecurityTokenFilter&lt;/filter-class&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
  &lt;filter-name&gt;SecurityTokenFilter&lt;/filter-name&gt;
  &lt;url-pattern&gt;/webapi/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;


&lt;/textarea&gt;

&lt;br /&gt;
&lt;br /&gt;
The ajax request which sends out the token in custom Http header and redirects to login page if server throws a 401 is depicted below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;$(document).ready(function() {
$.ajax({
    type: &#39;GET&#39;,
    url: &quot;my-url&quot;,
    dataType: &#39;json&#39;,
    data: &quot;{ &#39;name&#39;: &#39;somedata&#39;}&quot;,
    beforeSend: function (request){
        request.setRequestHeader(&quot;MyTokenField&quot;, localStorage.userToken);
    },
    success: function(mydata) {
        console.log(&#39;data ret=&#39;+JSON.stringify(mydata)) 
    },
    error: function(mydata){
        if(mydata.status === 401){
            alert(&#39;Redirecting you back to login page....&#39;);
            window.location = &quot;login.html&quot;;
        }
    }
});
 
});

&lt;/pre&gt;
I have&#39;nt put up the /login API, but its easy to imagine that, as a service which takes in username and password, and returns back a token.&lt;br /&gt;
&lt;br /&gt;
The above mechanism is still suspectible to man-in-the-middle attacks, for which the transport needs to be secured with SSL, any which ways. Libraries for generating hash as the unique token are available in javascript as well as java.&lt;br /&gt;
&lt;br /&gt;
The flexible thing about custom tokens, is that you can put in code on your server side to implement any particular policy for the token expiration. Example tokens can be to expire in a day or in a week. Also, keeping track of active users in your system is easier.&lt;br /&gt;
&lt;br /&gt;
I will leave the OAuth 2.0 two-legged mechanism for a subsequent article, since this one is getting too lengthy as it is :-)&lt;br /&gt;
&lt;br /&gt;
Hope you enjoyed the discussion above, related to basics of securing REST services.&lt;br /&gt;
&lt;br /&gt;
Cheers!</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/1173062980839427002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/1173062980839427002' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1173062980839427002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1173062980839427002'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2014/02/securing-your-rest-api.html' title='Securing your REST API'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1QdeljOzvtbnL-mVWBo5CQi4wDygzJExOjsF-reEM28ksU3ptF1mN5jF2FvbOkqrOwqdONLv523vCRlpo0Nu6kqZtujSKE1v9o9icouhrTB4Wh-l-I6jJKN3Huv_hfP7tpO-k66hddgr_/s72-c/sec2.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-4814869253843401322</id><published>2014-02-04T16:56:00.001+05:30</published><updated>2014-02-04T19:52:01.063+05:30</updated><title type='text'>Backbone.js - Getting Started Tutorial</title><content type='html'>When I started learning backbone.js, though there were several getting started tutorials, all of them seemed a little aggressive, since they introduced all the backbone features in a single, supposedly simple application. In this tutorial I am going to introduce each of backbone basic concepts incrementally and kind of provide a less steeper introduction to backbone.js for beginners.&lt;br /&gt;
&lt;br /&gt;
Lets jump right in....&lt;br /&gt;
&lt;br /&gt;
We will start out with a bare bones html file, which can be thought off, as the anchor or home page for the backbone application. Lets name it bb-intro.html.&lt;br /&gt;
&lt;br /&gt;
Initial listing of bb-intro.html&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifmRLgt0IRCEwagj1sH0x4QeadMUdfiWJOE-ZT4Lq8U2nFNB5eRKYyD-HKUstZPVwiobH7GbUtAc3xnvfICI4k1nGbvtZPJ3JIrRJheYYr2Pdi8Jrpi1hj2-3hzYW0nLMzRkSWHAY_HI3u/s1600/barehtml.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifmRLgt0IRCEwagj1sH0x4QeadMUdfiWJOE-ZT4Lq8U2nFNB5eRKYyD-HKUstZPVwiobH7GbUtAc3xnvfICI4k1nGbvtZPJ3JIrRJheYYr2Pdi8Jrpi1hj2-3hzYW0nLMzRkSWHAY_HI3u/s1600/barehtml.JPG&quot; height=&quot;364&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Next we will create a &quot;router&quot; in backbone, it is like a navigator component, which maps URLs to views/templates.&lt;br /&gt;
&lt;br /&gt;
Lets have 3 pages(views) in our application, to be able to display these on demand we will define the following routes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt; var AppRouter = Backbone.Router.extend({
   routes : {
    &quot;&quot; : &quot;showPage1&quot;,
    &quot;page1&quot; : &quot;showPage1&quot;,
    &quot;page2&quot; : &quot;showPage2&quot;,
    &quot;page3&quot; : &quot;showPage3&quot;
   },
   showPage1 : function() {
    new AppViewPage1().render();
   },
   showPage2 : function() {
    new AppViewPage2().render();
   },
   showPage3 : function() {
    new AppViewPage3().render();
   }
});
&lt;/pre&gt;
&lt;pre class=&quot;brush: java&quot;&gt;&lt;/pre&gt;
&lt;pre class=&quot;brush: java&quot;&gt; &amp;nbsp;&lt;/pre&gt;
&lt;pre class=&quot;brush: java&quot;&gt;var appRouter = new AppRouter();
Backbone.history.start();&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
The route entry &quot;&quot; implies the default html page and refers to the following URL&lt;br /&gt;
http://&amp;lt;host-name&amp;gt;:&amp;lt;port number&amp;gt;/&amp;lt;web-context&amp;gt;/&amp;lt;path-to-html&amp;gt;/bb-intro.html&lt;br /&gt;
or&lt;br /&gt;
http://&amp;lt;host-name&amp;gt;:&amp;lt;port number&amp;gt;/&amp;lt;web-context&amp;gt;/&amp;lt;path-to-html&amp;gt;/bb-intro.html#&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The entry &quot;page1&quot; refers to the following URL:&lt;br /&gt;
http://&amp;lt;host-name&amp;gt;:&amp;lt;port number&amp;gt;/&amp;lt;web-context&amp;gt;/&amp;lt;path-to-html&amp;gt;/bb-intro.html#page1&lt;br /&gt;
&lt;br /&gt;
The entry &quot;page2&quot; refers to the following URL:&lt;br /&gt;
http://&amp;lt;host-name&amp;gt;:&amp;lt;port number&amp;gt;/&amp;lt;web-context&amp;gt;/&amp;lt;path-to-html&amp;gt;/bb-intro.html#page2&lt;br /&gt;
&lt;br /&gt;
and so on....I think you get the picture here :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Next up, is the views like AppViewPage1, AppViewPage2, AppViewPage3, these are as you might have guessed javascript objects defined as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt; var AppViewPage1 = Backbone.View.extend({
  template : _.template($(&#39;#page1&#39;).html()),
  render : function() {
   $(&#39;#container&#39;).html(this.template());
  }
 });
  
  
 var AppViewPage2 = Backbone.View.extend({
  template : _.template($(&#39;#page2&#39;).html()),
  render : function() {
   $(&#39;#container&#39;).html(this.template());
  }
 });
  
 var AppViewPage3 = Backbone.View.extend({
  template : _.template($(&#39;#page3&#39;).html()),
  render : function() {
          $(&#39;#container&#39;).html(this.template());
  }
 });

&lt;/pre&gt;
&lt;br /&gt;
The code for each AppViewPage is quite simple stereotypical, for illustration purposes.

&lt;br /&gt;
We use the underscore library&#39;s api _.template( ) to load a template string&lt;br /&gt;
And in the view&#39;s render method, we simply assign html content of the div with id &quot;container&quot; using familiar jQuery syntax.&lt;br /&gt;
&lt;br /&gt;
Next up is the definitions of the template themselves. These are html templates containing valid html elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;textarea cols=&quot;80&quot; readonly=&quot;true&quot; rows=&quot;25&quot;&gt;&lt;script id=&quot;page1&quot; type=&quot;text/template&quot;&gt;
      &lt;div class=&quot;view&quot;&gt;
        &lt;h2&gt;This is Page 1&lt;/h2&gt;
        &lt;a href=&quot;#page2&quot;&gt;Goto Page 2&lt;/a&gt;
      &lt;/div&gt;
&lt;/script&gt;

 &lt;script id=&quot;page2&quot; type=&quot;text/template&quot;&gt;
      &lt;div class=&quot;view&quot;&gt;
        &lt;h2&gt;This is Page 2&lt;/h2&gt;
        &lt;a href=&quot;#page3&quot;&gt;Goto Page 3&lt;/a&gt;
      &lt;/div&gt;
&lt;/script&gt;
 
&lt;script id=&quot;page3&quot; type=&quot;text/template&quot;&gt;
      &lt;div class=&quot;view&quot;&gt;
        &lt;h2&gt;This is Page 3&lt;/h2&gt;
        &lt;a href=&quot;#page1&quot;&gt;Back to Page 1&lt;/a&gt;
      &lt;/div&gt;
&lt;/script&gt;

&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
Thats it!
When you access the above html in browser, it should show the following screens with proper navigation when clicked on the hyperlinks.&lt;br /&gt;
&lt;br /&gt;
Notice that the hrefs in the templates, refer to relative URLs, with values like &quot;#page1&quot;, &quot;#page2&quot; and &quot;#page3&quot;. This is same as the values we specified in the mapping in our router definition.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikWzWSDBcImEM6XEGpT8SPtGSernZ0EDGzfOL-JjShNfSjQ7NqTHyESZ8oWmUh294yUIs0F0IoeNZDd05uKU6v5qxzV0slGoMyaFxppqNhbeFbFRdjm4dA8-aVO7ieqsgNNLPKXBcIFMcl/s1600/barehtml1.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikWzWSDBcImEM6XEGpT8SPtGSernZ0EDGzfOL-JjShNfSjQ7NqTHyESZ8oWmUh294yUIs0F0IoeNZDd05uKU6v5qxzV0slGoMyaFxppqNhbeFbFRdjm4dA8-aVO7ieqsgNNLPKXBcIFMcl/s1600/barehtml1.JPG&quot; height=&quot;640&quot; width=&quot;373&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now that we are comfortable with navigating between views, using backbone. Lets turn our attention to features called model and collection provided by backbone.&lt;br /&gt;
&lt;br /&gt;
Lets jump right in by defining a model and collection and try to use the same in our view.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt; MyModel = Backbone.Model.extend({
  defaults : {
   title : &#39;Default Title&#39;,
   status : &#39;Initiated at &#39;+new Date(),
   attrib1 : &#39;Value1&#39;,
   attrib2 : &#39;Value2&#39;,
   attrib3 : &#39;Value3&#39;
  }
});

 MyCollection = Backbone.Collection.extend({
  model : MyModel,
 });
 
 var myCollection = new MyCollection();
 myCollection.add(new MyModel({title:&#39;Page1&#39;}));
 myCollection.add(new MyModel({title:&#39;Page2&#39;}));
 myCollection.add(new MyModel({title:&#39;Page3&#39;}));
 myCollection.add(new MyModel());

&lt;/pre&gt;
The above code defines a MyModel and MyCollection.
We then instantiate a MyCollection object and add 4 MyModel objects with custom titles.&lt;br /&gt;
&lt;br /&gt;
When the template is attached to the view, we need to additionally pass the collection as a template parameter.
This can be done as shown in the code below:&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;  
var AppViewPage1 = Backbone.View.extend({
template : _.template($(&#39;#page1&#39;).html()),
   render : function() {
 $(&#39;#container&#39;).html(this.template({mydata:myCollection.toJSON()}));
   }
});

&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
The template itself needs to be tweaked to iterate over the collection and start displaying the passed data parameters.
This can be easily done as seen in the snippet below:

&lt;textarea cols=&quot;80&quot; readonly=&quot;true&quot; rows=&quot;15&quot;&gt; 

&lt;script type=&quot;text/template&quot; id=&quot;page1&quot;&gt;
      &lt;div class=&quot;view&quot;&gt;
        &lt;h2&gt;This is Page 1&lt;/h2&gt;
        &lt;h2&gt;Data on page:&lt;/h2&gt;
        &lt;% _.each(mydata, function(row) { %&gt;
        &lt;%=row.title%&gt; &lt;br&gt;
        &lt;%  });   %&gt;

       &lt;br&gt;&lt;br&gt;
       &lt;a href=&quot;#page2&quot;&gt;Goto Page 2&lt;/a&gt;
      &lt;/div&gt;
&lt;/script&gt;

&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Apart from above mentioned features, the backbone model does provide the following important features:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Ability to listen to changes in model&lt;/b&gt;&lt;br /&gt;
In the model&#39;s initialize function, we can listen for changes to specific model attributes as follows:&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;initialize: function(){
            this.on(&quot;change:myattrib1&quot;, function(model){
                var newvalue = model.get(&quot;myattrib1&quot;);
                alert(&quot;Changed myattrib to &quot; + newvalue );
            });
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Interact transparently with a REST service back end&lt;/b&gt;&lt;br /&gt;
On the model we can invoke stock framework methods like save( ), destroy( ) and fetch( ), which result in HTTP methods PUT, POST, DELETE and GET, getting fired under the hood by the framework against a URL specified in the model&#39;s attribute called &#39;urlRoot&#39;.&lt;br /&gt;
&lt;br /&gt;
Thus there is no need to explicitly use jquery or ajax to make server side requests, the backbone.js model does it for you transparently.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;    var UserModel = Backbone.Model.extend({
        urlRoot: &#39;/user&#39;,
        defaults: {
            name: &#39;&#39;,
            email: &#39;&#39;
        }
    });

    var user = new Usermodel();
    // Notice that we haven&#39;t set an `id`
    var userDetails = {
        name: &#39;Ganesh Ghag&#39;,
        email: &#39;ganeshghag@gmail.com&#39;
    };

    // Because we have not set a `id` the server will call
    // issue a post  /user with a payload of userDetails data above
    // The server should save the data and return a response containing the new &#39;id&#39;
    user.save(userDetails, {
        success: function (user) {
            alert(user.toJSON());
        }
   })

&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Support for Model data validation&lt;/b&gt;&lt;br /&gt;
There is a provision in the backbone model to provide standard callback to validate model data before submission to server and also to raise error( ) callback in case validation fails. This is depicted below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;// If you return a string from the validate function,
// Backbone will throw an error
validate: function( attributes ){
            if( attributes.age &amp;lt; 0 ){
                return &quot;Negative values are not allowed&quot;;
            }
},
initialize: function(){
            this.bind(&quot;error&quot;, function(model, error){
                alert( error );
            });
}

&lt;/pre&gt;
So far we have been able to use backbone to display views, navigate between views and bind and show model data and collections, into the views.&lt;br /&gt;
&lt;br /&gt;
Lastly to attach events to elements in our backbone views is as easy as specifying events attribute of Backbone.View as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;SearchView = Backbone.View.extend({

        events: {
            &quot;click input[type=button]&quot;: &quot;doBtnClick&quot;
        },
        doBtnClick: function( event ){
            alert( &quot;from inside search button click&quot; );
        }
}

});

&lt;/pre&gt;
&lt;br /&gt;
With this we have covered most basics about the the backbone framework. You should now be heading towards more advanced tutorials on backbone.&lt;br /&gt;
&lt;br /&gt;
Cheers!&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/4814869253843401322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/4814869253843401322' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/4814869253843401322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/4814869253843401322'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2014/02/backbonejs-getting-started-tutorial.html' title='Backbone.js - Getting Started Tutorial'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifmRLgt0IRCEwagj1sH0x4QeadMUdfiWJOE-ZT4Lq8U2nFNB5eRKYyD-HKUstZPVwiobH7GbUtAc3xnvfICI4k1nGbvtZPJ3JIrRJheYYr2Pdi8Jrpi1hj2-3hzYW0nLMzRkSWHAY_HI3u/s72-c/barehtml.JPG" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7953107657166087832.post-1585766854838187950</id><published>2014-01-16T16:05:00.000+05:30</published><updated>2014-01-16T16:05:07.642+05:30</updated><title type='text'>Easy Bootstrap 3 based responsive web design using drag drop</title><content type='html'>Designing responsive web sites and user interfaces, which adjust their layouts and sizes depending on the device on which the website is being used, is all the rage now.&lt;br /&gt;
&lt;br /&gt;
Twitter bootstrap is the most popular framework for designing responsive websites. Bootstrap primarily uses CSS3, javascript, jquery and most importantly media queries to make a website responsive.&lt;br /&gt;
&lt;br /&gt;
But having to add all the botostrap css classes by-hand is quite painful and makes developers who are not designers cringe. Just when HTML/CSS builder tools were becoming easy to use, comes this little twist of using bootstrap responsive css classes all over html markup.&lt;br /&gt;
&lt;br /&gt;
Well, just found this little website,&amp;nbsp;&lt;a href=&quot;http://www.layoutit.com/&quot;&gt;http://www.layoutit.com&lt;/a&gt;, which allows developers to quickly build basic skeletons of bootstrap 3 based components, using drag and drop, instead of hand coding.&lt;br /&gt;
&lt;br /&gt;
I use it to quickly build a basic responsive page markup, then paste it in my IDE and fine-tune it from there on.&lt;br /&gt;
&lt;br /&gt;
This has definitely taken the pain out of remembering and putting in bootstrap class names by hand.&lt;br /&gt;
&lt;br /&gt;
Do check it out.&lt;br /&gt;
&lt;br /&gt;
This is a good convenience till more sophisticated and free tools for building responsive UIs come up in the market.</content><link rel='replies' type='application/atom+xml' href='http://ganeshghag.blogspot.com/feeds/1585766854838187950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7953107657166087832/1585766854838187950' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1585766854838187950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7953107657166087832/posts/default/1585766854838187950'/><link rel='alternate' type='text/html' href='http://ganeshghag.blogspot.com/2014/01/easy-bootstrap-3-based-responsive-web.html' title='Easy Bootstrap 3 based responsive web design using drag drop'/><author><name>Ganesh Ghag</name><uri>http://www.blogger.com/profile/05502034961798520349</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1j5RWI_QZluGMGe6125TZuB3VP6ijEfOzkZG4uSBuebaGuIzilQ9CRdSRe8RSjPIz7Q2-i0fJweB-zvcVcYiWf6eQxellAXoQ3mYbFqwSZrhYp1IqgA4TyOGxzho6vQ1ITVHoGiDWEGXfiMsz7APZVQsA7BFx8BsyW06xivkN01jMmQ/s220/ganeshghaginkedin-blacktshirt.jpeg'/></author><thr:total>8</thr:total></entry></feed>