<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tech-Freaks.com</title>
	<atom:link href="https://www.tech-freaks.com/feed" rel="self" type="application/rss+xml" />
	<link>https://www.tech-freaks.com</link>
	<description></description>
	<lastBuildDate>Wed, 22 Oct 2025 03:17:45 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.tech-freaks.com/wp-content/uploads/2025/07/cropped-tech-freaks-site-icon-512x512-1-32x32.png</url>
	<title>Tech-Freaks.com</title>
	<link>https://www.tech-freaks.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Making Sense of Agentforce: How Salesforce’s AI Agent Works Behind the Scenes</title>
		<link>https://www.tech-freaks.com/salesforce/agentforce/how-agentforce-works.html</link>
					<comments>https://www.tech-freaks.com/salesforce/agentforce/how-agentforce-works.html#respond</comments>
		
		<dc:creator><![CDATA[Tech Programmer]]></dc:creator>
		<pubDate>Mon, 20 Oct 2025 03:32:51 +0000</pubDate>
				<category><![CDATA[Agentforce]]></category>
		<category><![CDATA[Salesforce]]></category>
		<guid isPermaLink="false">https://www.tech-freaks.com/?p=223</guid>

					<description><![CDATA[When I started preparing for the Salesforce Agentforce Specialist certification, I realized something important. Reading Trailhead modules and following projects [&#8230;]]]></description>
										<content:encoded><![CDATA[		<div class="wpulike wpulike-default " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="223"
					data-ulike-nonce="b7bbe3a603"
					data-ulike-type="post"
					data-ulike-template="wpulike-default"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_223"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
			<div data-elementor-type="wp-post" data-elementor-id="223" class="elementor elementor-223">
				<div class="elementor-element elementor-element-86b57c3 e-flex e-con-boxed e-con e-parent" data-id="86b57c3" data-element_type="container" data-e-type="container">
					<div class="e-con-inner">
				<div class="elementor-element elementor-element-66b2932 elementor-widget elementor-widget-text-editor" data-id="66b2932" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>When I started preparing for the Salesforce Agentforce Specialist certification, I realized something important. Reading Trailhead modules and following projects inside Agentforce Builder Studio helped me complete the tasks, but I was still missing the big picture.</p><p>I often asked myself:<br />“How do all these parts — topics, actions, instructions, and prompts — actually work together when someone chats with the agent?”</p><p>If you are in the same boat, this article is for you. I am not writing this as an expert, but as someone learning and documenting the journey. If you notice anything that could be improved or clarified, please share feedback. My goal is to make this easier for anyone trying to understand how Agentforce fits together.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-6c1d95e elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="6c1d95e" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-59ab569 elementor-widget elementor-widget-heading" data-id="59ab569" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Before We Begin</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-6645a50 elementor-widget elementor-widget-text-editor" data-id="6645a50" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Agentforce is Salesforce’s framework for creating AI-powered agents that can reason, fetch information, and perform actions in your Salesforce environment.</p><p>When a user sends a message, Agentforce:<br />1. Understands what the user is asking (reasoning)<br />2. Retrieves the right data (actions)<br />3. Builds a grounded prompt for the model (prompt generation)<br />4. Returns a safe and validated response (output governance)</p><p>All of this happens within Salesforce. Only the model call to the LLM happens outside, protected by the Einstein Trust Layer.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-ed48959 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="ed48959" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-767a00b elementor-widget elementor-widget-heading" data-id="767a00b" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">What Agentforce Does</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-5c6a75f elementor-widget elementor-widget-text-editor" data-id="5c6a75f" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Agentforce is Salesforce’s framework for creating AI-powered agents that can reason, fetch information, and perform actions in your Salesforce environment.</p><p>When a user sends a message, Agentforce:<br />1. Understands what the user is asking (reasoning)<br />2. Retrieves the right data (actions)<br />3. Builds a grounded prompt for the model (prompt generation)<br />4. Returns a safe and validated response (output governance)</p><p>All of this happens within Salesforce. Only the model call to the LLM happens outside, protected by the Einstein Trust Layer.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-6f8992c elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="6f8992c" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-7d66ac6 elementor-widget elementor-widget-heading" data-id="7d66ac6" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Step-by-Step: What Happens When You Ask a Question</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-bd1bd1d elementor-widget elementor-widget-text-editor" data-id="bd1bd1d" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Imagine a user says:<br />&#8220;Where is my order?&#8221;<br />Let’s look at what happens behind the scenes.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-f510a2a elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="f510a2a" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-c79e5fd elementor-widget elementor-widget-image" data-id="c79e5fd" data-element_type="widget" data-e-type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
																<a href="https://www.tech-freaks.com/wp-content/uploads/2025/10/agentforce-architecture-diagram-scaled.png" data-elementor-open-lightbox="yes" data-elementor-lightbox-title="agentforce-architecture-diagram" data-e-action-hash="#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjI4LCJ1cmwiOiJodHRwczpcL1wvd3d3LnRlY2gtZnJlYWtzLmNvbVwvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAyNVwvMTBcL2FnZW50Zm9yY2UtYXJjaGl0ZWN0dXJlLWRpYWdyYW0tc2NhbGVkLnBuZyJ9">
							<img fetchpriority="high" decoding="async" width="1024" height="448" src="https://www.tech-freaks.com/wp-content/uploads/2025/10/agentforce-architecture-diagram-1024x448.png" class="attachment-large size-large wp-image-228" alt="Agentforce architecture diagram showing message flow across UI, Atlas Reasoning, Actions, Prompt and Einstein Trust Layer" srcset="https://www.tech-freaks.com/wp-content/uploads/2025/10/agentforce-architecture-diagram-1024x448.png 1024w, https://www.tech-freaks.com/wp-content/uploads/2025/10/agentforce-architecture-diagram-300x131.png 300w, https://www.tech-freaks.com/wp-content/uploads/2025/10/agentforce-architecture-diagram-768x336.png 768w, https://www.tech-freaks.com/wp-content/uploads/2025/10/agentforce-architecture-diagram-1536x672.png 1536w, https://www.tech-freaks.com/wp-content/uploads/2025/10/agentforce-architecture-diagram-2048x897.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" />								</a>
															</div>
				</div>
				<div class="elementor-element elementor-element-974d74e elementor-widget elementor-widget-text-editor" data-id="974d74e" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p><strong>Figure 1 — Agentforce end-to-end architecture.</strong></p><p>The diagram above shows how a message moves through different layers of Agentforce — from the chat widget to the Atlas reasoning engine, data fetch actions, prompt generation, and finally through the Einstein Trust Layer for validation and safety.</p><p><em>Color Key:</em><br />Cyan = UI Layer, Green = Atlas Reasoning, Amber = Actions &amp; Data, Purple = Prompt &amp; LLM Engine, Dashed Frame = Einstein Trust Layer.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-190e2df elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="190e2df" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-521f1bc elementor-widget elementor-widget-heading" data-id="521f1bc" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Layer 1: User Interface (Cyan)</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-5924092 elementor-widget elementor-widget-text-editor" data-id="5924092" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>This is where everything begins. The user types a message into the chat widget or another connected channel like Slack or Service Cloud Messaging.</p><p>Behind the scenes, the Context Manager tracks the conversation. It ensures that follow-up questions like &#8220;What about the second one?&#8221; make sense in context.</p><p>If you are building an agent, you can simulate this part using the Test Chat panel inside Agentforce Builder Studio. It lets you type questions and see how your agent responds without deploying it publicly.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-bba495f elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="bba495f" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-87f6f18 elementor-widget elementor-widget-heading" data-id="87f6f18" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Layer 2: Atlas Reasoning Layer (Green)</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-89013e8 elementor-widget elementor-widget-text-editor" data-id="89013e8" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>This is where the Atlas Engine takes over — the thinking part of Agentforce. The Atlas Reasoning Engine itself uses a specialized LLM under the hood to interpret the user’s intent, classify the right topic, merge instructions, and plan the next steps. You can think of it as the agent’s internal “logic brain,” separate from the later LLM call that generates the final text response.</p><p>In Agentforce Builder Studio, you create and configure Topics. Each topic represents a task or intent the agent can handle. For example, &#8220;Track Order,&#8221; &#8220;Reset Password,&#8221; or &#8220;Check Case Status.&#8221;</p><p>When you open or create a topic, you will see fields like:<br />&#8211; Topic Name and Description — define what this topic handles.<br />&#8211; Classification Description — explains the kind of questions that should trigger this topic. The reasoning engine uses this field heavily during Topic Classification.<br />&#8211; Example Phrases — optional text examples that help improve topic detection.<br />&#8211; Actions Section — where you connect the Flows, Apex, or Integrations that this topic can use.<br />&#8211; Instructions — where you define special guidelines for how the agent should respond when working on this topic.</p><p>When the user sends a message:<br />1. Topic Classification and Routing – Atlas checks the text and picks the most relevant topic.<br />2. Instruction Merge – Salesforce combines system-level, developer-level, and topic-level instructions.<br />3. Reasoning Planner – Atlas decides what happens next. It may ask a question, run an action, or use a prompt template.</p><p>You can sometimes see this reasoning process in the trace view when you test your agent. It shows which topic was selected and which actions were called.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-cf33620 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="cf33620" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-9114abd elementor-widget elementor-widget-heading" data-id="9114abd" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Layer 3: Action and Data (Amber)</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-4a453ab elementor-widget elementor-widget-text-editor" data-id="4a453ab" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Once Atlas knows what data it needs, it uses Actions that you linked to the topic earlier. Each action is either a Hydrator (pre-LLM) or an Effector (post-LLM).</p><p>Hydrators fetch data before the LLM call — for example, &#8220;Get Order Details&#8221; or &#8220;Fetch Case Notes&#8221;. These can be Salesforce Flows, Apex classes, or integrations.</p><p>The returned data becomes part of Grounded Business Data, also called context variables. These are the values that get merged into the prompt so the model can use real Salesforce data.</p><p>Effectors are actions that happen after the LLM call — for example, &#8220;Update Case&#8221; or &#8220;Send Password Reset&#8221;. They are also built using Flows or Apex.</p><p>All of these actions run directly inside Salesforce, powered by your org’s data and permissions.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-bad30e6 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="bad30e6" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-e7c478b elementor-widget elementor-widget-heading" data-id="e7c478b" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Layer 4: Prompt and LLM Engine (Purple)</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-ed3d4f7 elementor-widget elementor-widget-text-editor" data-id="ed3d4f7" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>This is where your agent’s language generation happens.</p><p>You create Prompt Templates in Prompt Builder. Each template defines a reusable structure, such as:</p><p>You are a helpful service agent.<br />Customer {{Customer.Name}}’s order {{Order.Number}} status is {{Order.Status}}.<br />Expected delivery: {{Order.ExpectedDelivery}}.</p><p>When Atlas calls this template:<br />1. The Prompt Composer fills in the variables.<br />2. The Trust Filter removes or masks sensitive data.<br />3. The LLM Call sends the cleaned prompt to the model.<br />4. The Output Validator checks that the model’s reply meets tone and safety rules.<br />5. The Structured Response is passed back to Atlas.</p><p>In Prompt Builder, you can also connect templates to Generation Fields to fill a field automatically in Salesforce, such as generating a case summary.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-32e3740 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="32e3740" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-4e21795 elementor-widget elementor-widget-heading" data-id="4e21795" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Einstein Trust Layer</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-baec533 elementor-widget elementor-widget-text-editor" data-id="baec533" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Everything from the hydrators to the LLM call runs inside the Einstein Trust Layer. It is Salesforce’s governance system for AI and ensures that:<br />&#8211; Sensitive data is redacted before leaving Salesforce.<br />&#8211; Prompts are grounded in Salesforce data.<br />&#8211; Model outputs are validated for safety and compliance.<br />&#8211; All activity is logged for auditing.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-e3aba9c elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="e3aba9c" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-5466981 elementor-widget elementor-widget-heading" data-id="5466981" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Response to the User</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-e64c5bf elementor-widget elementor-widget-text-editor" data-id="e64c5bf" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Atlas merges the structured response, executes any post-LLM actions, and sends the validated answer back through the Context Manager. The user then sees a clean, accurate response in the chat widget.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-75401c3 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="75401c3" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-46c9836 elementor-widget elementor-widget-heading" data-id="46c9836" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Why This Architecture Matters</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-1e14fb8 elementor-widget elementor-widget-text-editor" data-id="1e14fb8" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>1. Security and Trust – No sensitive data leaves Salesforce unprotected.<br />2. Grounded Accuracy – Answers come from real Salesforce data, not guesses.<br />3. Declarative Power – Admins and builders can design logic using Flows, Actions, and Prompt Templates without writing much code.<br />4. Governance – The Einstein Trust Layer ensures every AI call is tracked, redacted, and validated.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-89d1a24 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="89d1a24" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-0449891 elementor-widget elementor-widget-heading" data-id="0449891" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Wrapping Up</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-6de501d elementor-widget elementor-widget-text-editor" data-id="6de501d" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Agentforce is not just an LLM sitting inside Salesforce. It is a complete framework that:<br />&#8211; Uses Atlas to reason and plan,<br />&#8211; Uses Hydrators and Effectors to fetch and act on Salesforce data,<br />&#8211; Uses Prompt Builder to generate grounded and reusable prompts, and<br />&#8211; Relies on the Einstein Trust Layer to keep everything secure.</p><p>Once you understand how these layers connect, creating and debugging agents becomes much easier. It also makes studying for the Agentforce Specialist exam more meaningful because you can picture what is really happening behind every chat response.</p><p>If you notice any errors or think of ways to improve this explanation, please share your feedback. I am still learning, and I would love to keep refining this with your help.</p><p>For more detailed and official information, including examples and configuration references, check Salesforce’s own <a href="https://www.salesforce.com/agentforce/guide/" target="_blank" rel="nofollow noopener">Agentforce Guide</a>.</p><p> </p>								</div>
				</div>
					</div>
				</div>
				</div>
		]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-freaks.com/salesforce/agentforce/how-agentforce-works.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Mapping SFCC to CommerceTools: Part 1 – Architecture, APIs, and Core Commerce Features</title>
		<link>https://www.tech-freaks.com/ecommerce-platforms/mapping-sfcc-to-commercetools-part-1.html</link>
					<comments>https://www.tech-freaks.com/ecommerce-platforms/mapping-sfcc-to-commercetools-part-1.html#respond</comments>
		
		<dc:creator><![CDATA[Tech Programmer]]></dc:creator>
		<pubDate>Sun, 06 Jul 2025 22:27:52 +0000</pubDate>
				<category><![CDATA[E-Commerce Platforms]]></category>
		<category><![CDATA[commercetools]]></category>
		<category><![CDATA[salesforce b2c commerce]]></category>
		<category><![CDATA[sfcc]]></category>
		<guid isPermaLink="false">https://www.tech-freaks.com/?p=160</guid>

					<description><![CDATA[If you’ve spent years building storefronts, integrations, or backend logic in Salesforce Commerce Cloud (SFCC) using OCAPI, SCAPI, and Business [&#8230;]]]></description>
										<content:encoded><![CDATA[		<div class="wpulike wpulike-default " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="160"
					data-ulike-nonce="b7c62197a3"
					data-ulike-type="post"
					data-ulike-template="wpulike-default"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_160"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
			<div data-elementor-type="wp-post" data-elementor-id="160" class="elementor elementor-160">
				<div class="elementor-element elementor-element-bd0f603 e-flex e-con-boxed e-con e-parent" data-id="bd0f603" data-element_type="container" data-e-type="container">
					<div class="e-con-inner">
				<div class="elementor-element elementor-element-013a908 elementor-widget elementor-widget-text-editor" data-id="013a908" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p data-pm-slice="1 1 []">If you’ve spent years building storefronts, integrations, or backend logic in <strong>Salesforce Commerce Cloud (SFCC)</strong> using <strong>OCAPI</strong>, <strong>SCAPI</strong>, and <strong>Business Manager</strong>, switching to <strong>CommerceTools</strong> can feel like jumping into an entirely new paradigm. Where are the controllers? What happened to the familiar <code>beforeGET</code> and <code>modifyAfterPOST</code> hooks to intercept and modify API behavior? What’s the equivalent of custom objects? Where’s the Business Manager?</p>
<p>This article helps bridge that mental gap by mapping common SFCC concepts to their CommerceTools counterparts—starting with APIs, catalog, cart, and customer functionality.</p>
<p>Whether you&#8217;re an architect exploring headless options or a developer upskilling for a replatform, this guide is for you.</p>
<p>As a side note, one major strategic advantage of CommerceTools is that it offers a <strong>60-day trial environment</strong> to businesses and developers. This hands-on access makes it easier for architects, developers, and even business stakeholders to explore the platform&#8217;s capabilities and assess fit early in their decision-making process.</p>
<p>By contrast, Salesforce Commerce Cloud does <strong>not</strong> provide public or time-bound trial access, which limits experimentation, learning, and certification opportunities. This restriction can act as a barrier for new developers and consultants who might otherwise advocate for the platform. In the long run, this could put SFCC at a disadvantage, as developer and architect familiarity plays a major role in influencing platform adoption and enterprise decisions.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-037f77a elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="037f77a" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-86af150 elementor-widget elementor-widget-heading" data-id="86af150" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Business Manager vs Merchant Center</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-5083e99 elementor-widget elementor-widget-text-editor" data-id="5083e99" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p data-pm-slice="1 1 []">Before diving into APIs, it&#8217;s important to understand the role of each platform&#8217;s administrative console.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-9aec90f elementor-widget elementor-widget-html" data-id="9aec90f" data-element_type="widget" data-e-type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
					
<table>
  <thead>
    <tr>
      <th>Feature Area</th>
      <th>SFCC Business Manager</th>
      <th>CommerceTools Merchant Center</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Catalog Management</strong></td>
      <td>Full control over products, categories, price books</td>
      <td>Manage products, product types, categories, prices</td>
    </tr>
    <tr>
      <td><strong>User Roles & Permissions</strong></td>
      <td>Configure roles, permissions, organizations</td>
      <td>Manage users and roles for project access</td>
    </tr>
    <tr>
      <td><strong>Content & Slots</strong></td>
      <td>Page Designer, content assets, slots, A/B testing</td>
      <td>Very limited; content managed via external CMS</td>
    </tr>
    <tr>
      <td><strong>Custom Preferences</strong></td>
      <td>Site-specific preferences editable in BM</td>
      <td>Not available – config lives in custom fields or external systems</td>
    </tr>
    <tr>
      <td><strong>Job Schedules</strong></td>
      <td>Built-in job scheduler and logs</td>
      <td>No native jobs UI – use API/webhooks/integration</td>
    </tr>
    <tr>
      <td><strong>Order Management</strong></td>
      <td>View, edit, export orders</td>
      <td>View and search orders, some limited edits</td>
    </tr>
    <tr>
      <td><strong>Customer Management</strong></td>
      <td>View/edit customer profiles and address books</td>
      <td>View-only access; no rich customer admin tooling</td>
    </tr>
  </tbody>
</table>
				</div>
				</div>
				<div class="elementor-element elementor-element-fabe10e elementor-widget elementor-widget-text-editor" data-id="fabe10e" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p data-pm-slice="1 1 []"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Key Takeaway:</strong> The SFCC Business Manager is more mature and full-featured as an operational tool. In CommerceTools, the <strong>Merchant Center is API-first and minimal</strong>, meant to supplement—not replace—custom tooling. This means CommerceTools encourages businesses to build their own operational portals or use 3rd-party admin interfaces tailored to their workflow.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-ad6336a elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="ad6336a" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-b631bf8 elementor-widget elementor-widget-heading" data-id="b631bf8" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f30d.png" alt="🌍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Multi-Region Support Using Stores and Product Selections</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-007681e elementor-widget elementor-widget-text-editor" data-id="007681e" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p data-pm-slice="1 1 []">CommerceTools doesn’t use the concept of “Sites” like SFCC but enables similar multi-region or multi-brand configurations using:</p><ul data-spread="false"><li><p><strong>Stores</strong> – Each store represents a region or brand (e.g., US Store, CA Store)</p></li><li><p><strong>Product Selections</strong> – Assign products to specific stores as their catalog</p></li><li><p><strong>Channels</strong> – Optional layer for inventory/pricing scoping</p></li><li><p><strong>storeKey in API calls</strong> – Scopes customer, cart, and product responses to the intended store</p></li></ul><p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Example:</strong> To support both US and CA storefronts in the same project, you would:</p><ol start="1" data-spread="false"><li><p>Create two Stores (<code>us</code>, <code>ca</code>)</p></li><li><p>Assign product selections for each store</p></li><li><p>Use <code>GET /us/products</code> or <code>POST /ca/carts</code> to operate within a store’s context</p></li></ol><p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4ce.png" alt="📎" class="wp-smiley" style="height: 1em; max-height: 1em;" /> While customers exist at the project level, you can tag them to a store using <strong>Customer Groups</strong> or custom fields.</p><p>This gives you <strong>similar outcomes to SFCC’s site separation</strong>, but you manage the segmentation yourself through configuration and API conventions.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-53ec910 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="53ec910" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-5fc62da elementor-widget elementor-widget-heading" data-id="5fc62da" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f501.png" alt="🔁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> API Strategy and Architecture</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-cfd4729 elementor-widget elementor-widget-html" data-id="cfd4729" data-element_type="widget" data-e-type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
					<table>
  <thead>
    <tr>
      <th>Area</th>
      <th>SFCC</th>
      <th>CommerceTools</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>API Style</strong></td>
      <td>OCAPI (REST), SCAPI (REST + OAuth2)</td>
      <td>Pure API-first: REST and GraphQL</td>
    </tr>
    <tr>
      <td><strong>Auth</strong></td>
      <td>OCAPI: client ID & roles; SCAPI: SLAS (Shopper Login & API Access)</td>
      <td>OAuth2: supports <code>client_credentials</code>, <code>password</code>, <code>refresh_token</code> flows</td>
    </tr>
    <tr>
      <td><strong>Headless Readiness</strong></td>
      <td>Added gradually (SCAPI, Page Designer APIs)</td>
      <td>Built headless from the ground up</td>
    </tr>
    <tr>
      <td><strong>API Surface</strong></td>
      <td>Split across OCAPI and SCAPI (Shop, Data, Meta)</td>
      <td>Uniform access via REST and GraphQL across all domains</td>
    </tr>
  </tbody>
</table>
				</div>
				</div>
				<div class="elementor-element elementor-element-df5d59d elementor-widget elementor-widget-text-editor" data-id="df5d59d" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p data-pm-slice="1 1 []"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Key Difference:</strong> CommerceTools treats APIs as the <strong>primary interface</strong>, not a layer on top of a monolith. There’s no “Business Manager” style fallback—everything goes through the API.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-8e4e3c1 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="8e4e3c1" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-4640876 elementor-widget elementor-widget-heading" data-id="4640876" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">🛆 Product Catalog and Categories</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-c74a6f6 elementor-widget elementor-widget-text-editor" data-id="c74a6f6" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p data-pm-slice="1 1 []">For SFCC developers used to the layered catalog model—<strong>Master Catalog</strong>, <strong>Variation Groups</strong>, <strong>SKUs</strong>, and <strong>Navigation Catalogs</strong>—CommerceTools presents a flatter but more composable structure. Understanding how CommerceTools handles <strong>product modeling, variants, and attributes</strong> is key to transitioning smoothly.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-5e6a6e9 elementor-widget elementor-widget-html" data-id="5e6a6e9" data-element_type="widget" data-e-type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
					<table>
  <thead>
    <tr>
      <th>Concept</th>
      <th>SFCC</th>
      <th>CommerceTools</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Catalog</strong></td>
      <td>Master Catalog + Site-specific Navigation Catalog(s)</td>
      <td>No built-in separation; filtering by product selection or store context</td>
    </tr>
    <tr>
      <td><strong>Categories</strong></td>
      <td>Assigned per Navigation Catalog</td>
      <td>Hierarchical; assignable to products within a store or globally</td>
    </tr>
    <tr>
      <td><strong>Product Structure</strong></td>
      <td>Master, Variation Group, Variant</td>
      <td>Product with variants, defined via attributes and productType</td>
    </tr>
    <tr>
      <td><strong>Variation Attributes</strong></td>
      <td>Size, color, style etc. defined in variation model</td>
      <td>Driven by productType + attribute definitions</td>
    </tr>
    <tr>
      <td><strong>Product Attributes</strong></td>
      <td>Custom and system attributes</td>
      <td>Custom attributes via productType; typed and validated</td>
    </tr>
    <tr>
      <td><strong>SKU Level</strong></td>
      <td>Variant ID (SKU) managed in variation matrix</td>
      <td>Each variant is its own object with SKU and attributes</td>
    </tr>
  </tbody>
</table>
				</div>
				</div>
				<div class="elementor-element elementor-element-27251e1 elementor-widget elementor-widget-text-editor" data-id="27251e1" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<h5><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f501.png" alt="🔁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> What Changes</h5><ul data-spread="false"><li><p><strong>No three-level hierarchy</strong> like Master → Variation Group → Variant. In CommerceTools, there are only products and variants based on the variant-defining attributes.</p></li><li><p><strong>Product Types</strong> are mandatory. You define them with a schema of attributes before any product creation.</p></li><li><p>Each <strong>attribute</strong> is reusable and can be configured with <code>attributeConstraint = CombinationUnique</code> and <code>level = variant</code> to drive variant combinations.</p></li><li><p><strong>No site-specific price books</strong> — prices live directly on variants with <code>currencyCode</code> and optional <code>channel</code>.</p></li></ul><h5><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Gotchas &amp; Tips</h5><ul data-spread="false"><li><p>CommerceTools doesn’t enforce product uniqueness at the catalog level — you must manage slugs and keys carefully.</p></li><li><p>There is no visual matrix like SFCC’s VG editor — variant definitions are more flexible but require thoughtful schema.</p></li><li><p>All variant combinations must be explicitly created — CT does not auto-generate them.</p></li><li><p>The UI in Merchant Center uses <strong>&#8220;level: variant&#8221;</strong> to indicate variant-defining attributes. In the API, this is modeled using <code>attributeConstraint = CombinationUnique</code>. </p></li></ul><h5><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Clarification:</h5><p>A <strong>ProductType</strong> in CommerceTools is not equivalent to a single variation attribute in SFCC—it&#8217;s broader. It defines the full schema for a product, including both product-level and variant-level attributes.</p><ul data-spread="false"><li><p>Attributes with <code>level: variant</code> and <code>attributeConstraint = CombinationUnique</code> help resolve a product down to a <strong>specific variant</strong> (SKU). These are equivalent to SFCC <strong>Variation Attributes</strong>.</p></li><li><p>Attributes with <code>level: product</code> are more like <strong>standard attributes</strong> in SFCC—they apply to the entire product and do not influence variant resolution.</p></li></ul><p>This separation allows CommerceTools to clearly distinguish between what identifies a variant and what describes a product.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-066b918 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="066b918" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-3ec4bc8 elementor-widget elementor-widget-heading" data-id="3ec4bc8" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6d2.png" alt="🛒" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Cart and Checkout Flow</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-5a2d86b elementor-widget elementor-widget-html" data-id="5a2d86b" data-element_type="widget" data-e-type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
					<table>
  <thead>
    <tr>
      <th>Capability</th>
      <th>SFCC</th>
      <th>CommerceTools</th>
    </tr>
  </thead>
  <tbody>
<tr>
      <td><strong>Cart Modification</strong></td>
      <td>Via pipelines/controllers or SCAPI</td>
      <td>Atomic operations via API (addLineItem, removeLineItem)</td>
    </tr>
    <tr>
      <td><strong>Coupon Handling</strong></td>
      <td>Promotion engine with coupons</td>
      <td>Discount codes + Cart Discounts via rules</td>
    </tr>
    <tr>
      <td><strong>Custom Logic</strong></td>
      <td>Custom hooks, pipelines, controllers</td>
      <td>Can trigger AWS Lambda (or similar) via API extension hooks</td>
    </tr>
    <tr>
      <td><strong>Committing Cart</strong></td>
      <td>SubmitOrder or SCAPI call creates order</td>
      <td>Explicit transition via API: cart → order</td>
    </tr>
    <tr>
      <td><strong>Inventory Check</strong></td>
      <td>Real-time check via inventory list / ATS</td>
      <td>API-based channel inventory per SKU</td>
    </tr>
  </tbody>
</table>
				</div>
				</div>
				<div class="elementor-element elementor-element-b7f62c7 elementor-widget elementor-widget-text-editor" data-id="b7f62c7" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p data-pm-slice="1 1 []"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Big Shift</strong></p>
<p>In SFCC, cart and checkout behavior is controlled by embedded logic such as hooks and pipelines, which run inside the platform. In CommerceTools, this logic is <strong>externalized</strong>. You use <strong>API Extensions</strong> to trigger custom logic via HTTP calls before changes are committed—like validating a cart or syncing an order. This shift enables greater flexibility but also requires your team to manage cloud functions or middleware.</p>
<h5><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f527.png" alt="🔧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> How to Add Custom Logic in Cart/Checkout (CommerceTools)</h5>
<p>In SFCC, developers rely on <strong>hooks</strong> (<code>beforePOST</code>, <code>modifyGET</code>, etc.) to intercept or inject logic into the cart and checkout flows. CommerceTools takes a different approach.</p>
<p>To customize or extend cart/checkout behavior:</p>
<ul data-spread="false">
<li>
<p>Use <strong>API Extensions</strong> to register <strong>event-driven triggers</strong> on specific resources (e.g., cart creation, order creation)</p>
</li>
<li>
<p>These triggers can call an external service like an <strong>AWS Lambda</strong>, <strong>GCP Cloud Function</strong>, or <strong>HTTP webhook endpoint</strong></p>
</li>
</ul>
<p>For example:</p>
<ul data-spread="false">
<li>
<p>On <code>order.created</code>, you could trigger a webhook that syncs to an ERP</p>
</li>
<li>
<p>On <code>cart.changed</code>, validate inventory or inject promotions</p>
</li>
</ul>
<p>There is <strong>no direct inline logic execution</strong> within CommerceTools like SFCC hooks. Instead, CT encourages <strong>decoupled, serverless logic</strong> that lives in your infrastructure.</p>
<h5><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Pro Tip:</h5>
<p>Use CommerceTools’ <a href="https://docs.commercetools.com/api/projects/api-extensions" target="_blank" rel="noopener">API Extension mechanism</a> to replicate SFCC-style logic points. These extensions:</p>
<ul data-spread="false">
<li>
<p>Can intercept changes before they&#8217;re committed to the DB (e.g., validate a cart before save)</p>
</li>
<li>
<p>Allow asynchronous workflows (e.g., trigger webhook on order create)</p>
</li>
<li>
<p>Provide language-agnostic flexibility via HTTP</p>
</li>
</ul>
<p>Unlike SFCC’s inline controller logic or hook files, CommerceTools encourages decoupling core logic into cloud-native or external services.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-a1d5188 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="a1d5188" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-bab0037 elementor-widget elementor-widget-heading" data-id="bab0037" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f464.png" alt="👤" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Customer Management &amp; Sessions</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-1122ed6 elementor-widget elementor-widget-html" data-id="1122ed6" data-element_type="widget" data-e-type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
					<table>
  <thead>
    <tr>
      <th>Feature</th>
      <th>SFCC</th>
      <th>CommerceTools</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Customer Types</strong></td>
      <td>Registered or Guest</td>
      <td>Registered or Anonymous</td>
    </tr>
    <tr>
      <td><strong>Login</strong></td>
      <td>Handled via OCAPI/SCAPI or storefront login</td>
      <td>OAuth2 password grant or token-based login APIs</td>
    </tr>
    <tr>
      <td><strong>Session Tokens</strong></td>
      <td>SCAPI uses bearer tokens (SLAS); OCAPI uses cookie/session</td>
      <td>OAuth2 bearer tokens with expiration and refresh flows</td>
    </tr>
    <tr>
      <td><strong>Customer Scope</strong></td>
      <td>Scoped per site (login required on each)</td>
      <td>Global to project; can filter/group using custom fields</td>
    </tr>
    <tr>
      <td><strong>Password & Reset</strong></td>
      <td>Storefront flows or OCAPI</td>
      <td>Handled via Customer API or Compose Frontend login flows</td>
    </tr>
    <tr>
      <td><strong>Custom Attributes</strong></td>
      <td>Defined in Business Manager</td>
      <td>Typed custom fields defined on customer schema</td>
    </tr>
  </tbody>
</table>
				</div>
				</div>
				<div class="elementor-element elementor-element-e14134a elementor-widget elementor-widget-text-editor" data-id="e14134a" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p data-pm-slice="1 1 []"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Clarification for SFCC Developers:</strong></p>
<p>Both platforms use OAuth-based bearer tokens to authenticate and authorize customer requests. You pass the token with every API call, and both support guest (anonymous) and registered customer flows.</p>
<p><strong>In SFCC</strong>, SLAS (Shopper Login and API Access Service) is available only with SCAPI—not OCAPI. It provides a managed identity layer that handles token issuance, refresh, expiration, and device activation flows. For OCAPI, authentication is handled through client credentials configured with specific roles.</p>
<p><strong>In CommerceTools</strong>, the authentication flow is standards-based (OAuth2), but you manage token storage, refresh, and lifecycle within your frontend or middleware (e.g., <strong>Composable Frontend</strong>, the official frontend framework offered by CommerceTools, formerly known as Frontastic).</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f538.png" alt="🔸" class="wp-smiley" style="height: 1em; max-height: 1em;" /> So, for most implementations, the developer experience is <strong>functionally similar</strong>, especially with the right framework. The key difference is that CommerceTools doesn’t provide a proprietary session management layer like SLAS—you either roll your own or adopt a tool that does.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Developer Note:</strong> There’s no Business Manager-style UI to manage customer data in CommerceTools—you’ll likely build your own admin interface or connect a 3rd-party system via API.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-edfb04b elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="edfb04b" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-db3074b elementor-widget elementor-widget-heading" data-id="db3074b" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Wrapping Up: From SFCC to Composable Thinking</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-b983a8d elementor-widget elementor-widget-text-editor" data-id="b983a8d" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p data-pm-slice="1 1 []">CommerceTools removes the concept of site-specific logic and server-side pipelines. Instead, it gives you <strong>clean APIs, well-defined resources, and full flexibility to assemble your stack</strong> using modern frontend, backend, and middleware technologies.</p>
<p>As an SFCC veteran, you&#8217;ll likely miss some out-of-the-box conveniences (e.g., Business Manager tools or controller-based flows), but you&#8217;ll gain far more in terms of <strong>architecture flexibility, speed, and future-proofing</strong>.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Mindset Shift:</strong> CommerceTools expects you to <strong>think API-first</strong>, not console-first. Most platform capabilities—including product, cart, checkout, and even promotions—are driven by APIs, not by built-in tools or wizards. While the Merchant Center provides some UI for business users, serious customization happens outside the box.</p>
<p>In fact, CommerceTools is designed to <strong>act as a modular commerce engine</strong>—just one part of your broader digital commerce stack. You may combine it with a custom frontend (like Composable Frontend), third-party CMS, payment processor, or tax engine, all loosely coupled via API.</p>
<p>This modular, API-first mindset is key to unlocking the power of composable commerce.</p>								</div>
				</div>
					</div>
				</div>
				</div>
		]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-freaks.com/ecommerce-platforms/mapping-sfcc-to-commercetools-part-1.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Custom datetime picker composable with jetpack compose</title>
		<link>https://www.tech-freaks.com/app-development/jetpack-compose/custom-datetime-picker-android.html</link>
					<comments>https://www.tech-freaks.com/app-development/jetpack-compose/custom-datetime-picker-android.html#respond</comments>
		
		<dc:creator><![CDATA[Tech Programmer]]></dc:creator>
		<pubDate>Wed, 20 Mar 2024 04:07:49 +0000</pubDate>
				<category><![CDATA[Jetpack Compose]]></category>
		<guid isPermaLink="false">http://localhost/tfcom_wp/2024/03/20/custom-datetime-picker-android/</guid>

					<description><![CDATA[Recently, I started working on a new Android project using Jetpack compose. I wanted to have two datetime field to [&#8230;]]]></description>
										<content:encoded><![CDATA[		<div class="wpulike wpulike-default " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="97"
					data-ulike-nonce="8664dd9d64"
					data-ulike-type="post"
					data-ulike-template="wpulike-default"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_97"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p style="text-align: left;">Recently, I started working on a new Android project using Jetpack compose. I wanted to have two datetime field to capture start datetime and end datetime using the inbuilt pickers. The date and time selected from the picker should populate single text field with date and time together or two separate text fields representing the date and time respectively.</p>
<p style="text-align: left;">Much to my surprise there are no datetime picker composable as of now. Furthermore, I realized that <a title="DatePickerDialog" href="https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#DatePickerDialog(kotlin.Function0,kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Function0,androidx.compose.ui.graphics.Shape,androidx.compose.ui.unit.Dp,androidx.compose.material3.DatePickerColors,androidx.compose.ui.window.DialogProperties,kotlin.Function1)" target="_blank" rel="nofollow noopener"> DatePickerDialog</a> and <a title="DatePicker" href="https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#DatePicker(androidx.compose.material3.DatePickerState,androidx.compose.ui.Modifier,androidx.compose.material3.DatePickerFormatter,kotlin.Function0,kotlin.Function0,kotlin.Boolean,androidx.compose.material3.DatePickerColors)" target="_blank" rel="nofollow noopener">DatePicker </a>exists but managing populating the text field with DatePicker state needs to be done by custom code. Finally, for time, <a title="TimePicker" href="https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#TimePicker(androidx.compose.material3.TimePickerState,androidx.compose.ui.Modifier,androidx.compose.material3.TimePickerColors,androidx.compose.material3.TimePickerLayoutType)" target="_blank" rel="nofollow noopener">TimePicker</a> exists but there is no out of the box TimePickerDialog as of now. In the post, I am sharing the custom datetime composable that I created to accomplish my requirements.</p>
<p><span id="more-97"></span></p>
<h3 style="text-align: left;">DateTimePicker Preview</h3>
<p><img decoding="async" class="float-none" src="https://www.tech-freaks.com/wp-content/uploads/2024/03/custom_datetime_picker_demo.gif" width="234" height="520"></p>
<p>The below code when added inside a <em>column </em>will render the two datetime fields.</p>
<pre class="language-java"><code>       CustomDateTimePicker(
            title = "Start datetime",
            state = startDateTimeState
        )
        CustomDateTimePicker(
            title = "End datetime",
            state = endDateTimeState
        )</code></pre>
<p>The complete running code can be downloaded from the github repository.</p>
<h4 style="text-align: left;">Github Repo: <a title="Custom DateTimePicker App" href="https://github.com/tech-freaks/MyDateTimePickerApp" target="_blank" rel="nofollow noopener">MyDateTimePicker App</a></h4>
<h3 style="text-align: left;">High-level design</h3>
<p>Below are the different components written to create and display the datetime composable.</p>
<h4>DateTimePicker.kt</h4>
<p>The method <em>CustomDateTimePicker </em>is the top-level composable that would generate a datetime composable. It internally calls the <em>CustomDatePicker </em>and <em>CustomTimePicker </em>composable. These two composables utilize the Dialog and Picker to display the date or time strings in a text field. The <em>CustomDateTimePicker </em>uses an mutable state object of type of LocalDateTime class. This object is set with the date and time picked by the user and displayed in the date and time text fields.</p>
<h4>TFDateUtils.kt</h4>
<p>The object provides different utility methods for manipulating LocalDate, LocalDateTime, String and Long milliseconds. These methods are used from the different composable methods in DateTimePicker.kt.</p>
<h3>Code walk-through </h3>
<p>The <em>DatePickerState </em>and <em>TimePickerState </em>manage the state of the Date and Time picker. Initialized differently, I created mutable state strings to remember the date and time value to be displayed on the text fields. Ideally, I wanted to use the DatePickerState and TimePickerState to directly set the value in the text fields. But, these objects updated even when the user uses the picker, selects the data or time and cancels or dismisses the dialog. </p>
<pre class="language-java"><code>val displayDate = remember {
        mutableStateOf(TFDateUtils.getCurrentDateString(dateFormat))
    }</code></pre>
<p>As mentioned earlier, jetpack compose does not have a <em>TimePickerDialog</em>. I used the composable written in the article <a title="Exploring Date and Time Pickers: Compose Bytes" href="https://medium.com/@droidvikas/exploring-date-and-time-pickers-compose-bytes-120e75349797" target="_blank" rel="nofollow noopener">Exploring Date and Time Pickers: Compose Bytes</a>.</p>
<p>Lastly, in the CustomDateTimePicker composable, I created a lambda function to update the LocalDateTime with the DatePickerState and TimePickerState value (or the default initial values). This function is passed to the <em>CustomDatePicker </em>and <em>CustomTimePicker </em>composable, so the function can be called every time the user selects a new date or time.  </p>
<pre class="language-java"><code>val updateState = {
        val dateString = if (dateState.selectedDateMillis != null) {
            TFDateUtils.convertMillisToDateString(
                millis = dateState.selectedDateMillis!!,
                format = dateFormat
            )
        } else {
            TFDateUtils.getCurrentDateString(dateFormat)
        }
        val timeString = if (timePickerState.minute != null 
                                               &amp;&amp; timePickerState.hour != null) {
            TFDateUtils.getTimeString(
                hour = timePickerState.hour,
                min = timePickerState.minute
            )
        } else {
            TFDateUtils.getCurrentTimeString(timeFormat)
        }
        state.value = TFDateUtils.getLocalDataTimeFromString(
            dateTime = "$dateString $timeString",
            format = dateTimeFormat
        )
    }</code></pre>
<p>I have used a Toast to display the value of the LocalDateTime state set by the CustomDateTimePicker composable. In the real-world, this will probably need a converter to convert to string and save it to Rooms database through a ViewModel. </p>
<h3>Known issues and improvements</h3>
<ul>
<li>The current implementation has some glitch when either date or time is selected but not both. The LocalDateTime state object needs to be synchronized better with the displayDate and displayTime mutable state strings to prevent this issue.</li>
<li>Using OffSetDateTime instead of LocalDateTime will help account for timezone, especially when the device moves between timezones. </li>
</ul>
<p> </p>
<p>Hope the article provided a good starting point to create a custom datetime picker composable that can be reused by quickly adding to other composable.</p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-freaks.com/app-development/jetpack-compose/custom-datetime-picker-android.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Multiple ways to add sub elements to XML elements using Python</title>
		<link>https://www.tech-freaks.com/python/add-subelement-xml.html</link>
					<comments>https://www.tech-freaks.com/python/add-subelement-xml.html#respond</comments>
		
		<dc:creator><![CDATA[Tech Programmer]]></dc:creator>
		<pubDate>Wed, 28 Feb 2024 04:31:14 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">http://localhost/tfcom_wp/2024/02/28/add-subelement-xml/</guid>

					<description><![CDATA[Recently, I have been working on manipulating xmls and csvs using Python. I was amazed by how quick and easy [&#8230;]]]></description>
										<content:encoded><![CDATA[		<div class="wpulike wpulike-default " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="95"
					data-ulike-nonce="de26b3a82d"
					data-ulike-type="post"
					data-ulike-template="wpulike-default"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_95"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p style="text-align: left;">Recently, I have been working on manipulating xmls and csvs using Python. I was amazed by how quick and easy it is manipulate these files in Python. In this article I cover the flexibility of the python and xml.etree.ElementTree API. Let us jump into it.</p>
<h4 style="text-align: left;">Problem</h4>
<p style="text-align: left;">Given a dictionary of words and meaning in multiple language. We want to manipulate the xml and add another meaning in French language for the word <em>beauty. </em></p>
<p><span id="more-95"></span></p>
<pre class="language-markup"><code>&lt;dictionary&gt;
    &lt;definition&gt;
        &lt;word lang="en-US"&gt;beauty&lt;/word&gt;
        &lt;meaning lang="en-US"&gt;
            a combination of qualities, such as shape, color, or form, that pleases the aesthetic senses, especially the sight.
        &lt;/meaning&gt;
    &lt;/definition&gt;
&lt;/dictionary&gt;</code></pre>
<h4 style="text-align: left;">Approach 1</h4>
<p style="text-align: left;">The simplest approach is to find / reach the element of <em>definition. </em>Then add a sub-element <em>meaning </em>to the <em>definition. </em>This would look something like below.</p>
<pre class="language-python"><code>import xml.etree.ElementTree as ET

# Parse the XML file
tree = ET.parse('sample.xml')
root = tree.getroot()

beauty_meaning_fr = "La beauté est l'harmonie des formes et des couleurs qui évoque un sentiment d'émerveillement et d'admiration."

def_elements = root.findall('definition')

for definition in def_elements:
    word = definition.find('word')
    if word.text == 'beauty':
        new_meaning = ET.SubElement(definition, 'meaning')
        new_meaning.text = beauty_meaning_fr
        new_meaning.set('lang', 'fr-FR')

tree.write('output.xml')</code></pre>
<p style="text-align: left;">This approach works great and provides the desired output.</p>
<pre class="language-markup"><code>&lt;dictionary&gt;
    &lt;definition&gt;
        &lt;word lang="en-US"&gt;beauty&lt;/word&gt;
        &lt;meaning lang="en-US"&gt;
            a combination of qualities, such as shape, color, or form, that pleases the aesthetic senses, especially the sight.
        &lt;/meaning&gt;
    &lt;meaning lang="fr-FR"&gt;La beaut&amp;#233; est l'harmonie des formes et des couleurs qui &amp;#233;voque un sentiment d'&amp;#233;merveillement et d'admiration.&lt;/meaning&gt;&lt;/definition&gt;
&lt;/dictionary&gt;</code></pre>
<p style="text-align: left;">However, when I was working on my real-life problem, the above code did not add the <em>meaning </em>element for some reason. Hence, I started looking for another approach to solve my issue.</p>
<h3 style="text-align: left;">Approach 2</h3>
<p style="text-align: left;">Another option is to add a new element <em>meaning</em>, instead of a sub-element. Of course, the element will then need to added to another element. To achieve our requirement, we need to reach the <em>definition </em>element and insert or append the <em>meaning</em> element that we initially created. The below code summarizes this approach:</p>
<pre class="language-python"><code>import xml.etree.ElementTree as ET

# Parse the XML file
tree = ET.parse('sample.xml')
root = tree.getroot()

beauty_meaning_fr = "La beauté est l'harmonie des formes et des couleurs qui évoque un sentiment d'émerveillement et d'admiration."

def_elements = root.findall('definition')

for definition in def_elements:
    word = definition.find('word')
    if word.text == 'beauty':
        new_meaning = ET.Element("meaning")
        new_meaning.text = beauty_meaning_fr
        new_meaning.set('lang', 'fr-FR')
        definition.append(new_meaning)

tree.write('output1.xml')</code></pre>
<p style="text-align: left;">The code works as expected and generates the output similar to that of approach 1.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-freaks.com/python/add-subelement-xml.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>RESTful service using Spring MVC and Hibernate</title>
		<link>https://www.tech-freaks.com/java/jsp-servlets/rest-service-spring-hibernate.html</link>
					<comments>https://www.tech-freaks.com/java/jsp-servlets/rest-service-spring-hibernate.html#respond</comments>
		
		<dc:creator><![CDATA[Tech Programmer]]></dc:creator>
		<pubDate>Sat, 11 Jul 2015 16:28:17 +0000</pubDate>
				<category><![CDATA[JSP & Servlets]]></category>
		<guid isPermaLink="false">http://localhost/tfcom_wp/2015/07/11/rest-service-spring-hibernate/</guid>

					<description><![CDATA[Requirement Create a RESTful service using Spring MVC and Hibernate for fetching, adding, updating and deleting product information.  The product [&#8230;]]]></description>
										<content:encoded><![CDATA[		<div class="wpulike wpulike-default " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="9"
					data-ulike-nonce="148a8cbc6a"
					data-ulike-type="post"
					data-ulike-template="wpulike-default"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_9"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p style="text-align: left;"><strong>Requirement</strong></p>
<p style="text-align: left;">Create a RESTful service using Spring MVC and Hibernate for fetching, adding, updating and deleting product information.  The product information will be persisted in a database table. The service should be available to be consumed by any client like mobile, html, java application etc. using the REST url created.</p>
<p style="text-align: left;"><strong>GitHub Project URL</strong></p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><strong><span style="font-size: 10pt;"><a style="color: #1b57b1; text-decoration: none; font-weight: normal;" href="https://github.com/tech-freaks/catalog-service" target="_blank" rel="alternate noopener noreferrer">https://github.com/tech-freaks/catalog-service</a></span></strong></p>
<p style="text-align: left;"><strong>Pre-requisites</strong></p>
<ul style="text-align: left;">
<li>MySQL and Tomcat is already installed</li>
<li>Eclipse with JEE support is already installed</li>
<li>Basics about Spring and Hibernate framework</li>
<li>Basics about RESTful service</li>
</ul>
<p><span id="more-9"></span></p>
<p style="text-align: left;"><strong>Analysis and Design</strong></p>
<p style="text-align: left;">We will use a bottom-up approach to design our application. We start from the database layer, then hibernate layer and finally the Spring layer.</p>
<p style="text-align: left;">Database</p>
<p>For implementing this requirement, we create a table PRODUCT. It has basic information about a product like name, description, partnumber, unit price etc. We do not have any more table for fulfilling this requirement. However, if you create a complex application, your product information might be normalized into multiple related tables.</p>
<p style="text-align: left;">Below is the CREATE table statement for creating the PRODUCT table.</p>
<pre class="brush:sql" style="color: #333333; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;"> CREATE TABLE IF NOT EXISTS `product` (
  `product_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `partnumber` varchar(50) NOT NULL,
  `description` varchar(1024) NOT NULL,
  `thumbnail_url` varchar(240) DEFAULT NULL,
  `buyable` char(1) NOT NULL DEFAULT 'Y',
  `unitprice` decimal(8,2) NOT NULL,
  PRIMARY KEY (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;</pre>
<p style="text-align: left;">There is two sql script in the github repository root folder create_tables.sql and product_load.sql. As the name suggests, the first sql can be used to create a database and PRODUCT table. The second sql can be run to insert some starter products.</p>
<p style="text-align: left;"><span style="text-decoration: underline;">Hibernate</span></p>
<p style="text-align: left;">Nothing to think about here! We will have a hibernate class Product.java which will be mapped to PRODUCT table. If you would want to reverse engineer the Product.java from the database table, review the steps in the article <a title="Reverse Engineering Hibernate objects using JBoss eclipse plugin" href="jsp-servlets/jboss-reverse-engineer-hibernate.html" target="_blank" rel="alternate noopener noreferrer">Reverse Engineering Hibernate objects using JBoss eclipse plugin</a></p>
<p style="text-align: left;"><span style="text-decoration: underline;">Spring</span></p>
<p style="text-align: left;">We will have a single Controller, which will have different methods for each verb like GET, PUT, POST and DELETE and will act upon Product table data. Following the Spring convention, we will interact with the database using the following layered approach</p>
<p style="text-align: left;">Spring Controller -&gt; Service -&gt; DAO -&gt; Hibernate -&gt; Database</p>
<p style="text-align: left;"><em>Spring Controller:</em><br />
CatalogRestController</p>
<p style="text-align: left;"><em>Service</em>:<br />
ProductService<br />
ProductServiceImpl</p>
<p style="text-align: left;"><em>DAO</em>:<br />
ProductDAO<br />
ProductDAOImpl</p>
<p style="text-align: left;">Furthermore, the Rest controller will have the following methods</p>
<pre class="language-java"><code>@RequestMapping(method = RequestMethod.GET)
public List&lt;Product&gt; getProducts(); - Get all products

@RequestMapping(value = "/{productId}", method = RequestMethod.GET)
public ResponseEntity&lt;?&gt; getProduct(@PathVariable Integer productId) &lt;- Get Products with ProductId

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity&lt;?&gt; add(@RequestBody Product input) &lt;- Insert a product for input received

@RequestMapping(value = "/{productId}", method = RequestMethod.PUT)
public ResponseEntity&lt;?&gt; update(@PathVariable Integer productId,
@RequestBody Product input) &lt;- Update product information for productId

@RequestMapping(value = "/{productId}", method = RequestMethod.DELETE)
public ResponseEntity&lt;?&gt; remove(@PathVariable Integer productId) &lt;- Delete product for the provided productId</code></pre>
<p style="text-align: left;">The above also shows at a high level usage of Spring annotations for specifying different verbs.</p>
<blockquote><p><span style="text-decoration: underline;">Word of caution</span>: This design allows a REST client to insert, delete or update records in database, without any authentication and authorization. For a production application, generally, the only verb which might allow access without authorization is the GET. All the other verbs which modify the database might be authenticated and authorized. Oauth is a commonly used open standard of authorization used to authorize client before they can make changes to the underlying data source.</p></blockquote>
<p style="text-align: left;">We will need to further create XML configuration file for web application, Spring framework and add libraries. We will cover this in environment setup and development sections.</p>
<hr class="system-pagebreak" title="Environment Setup" />
<p style="text-align: left;"><strong>Environment Setup</strong></p>
<ul style="text-align: left;">
<li>Open eclipse and create a &#8220;Dynamic Web Project&#8221; in eclipse with the name &#8220;catalog-service&#8221;.</li>
<li>Click next, then next and finish.</li>
<li>If you are using Maven or Gradle, setup to download libraries for Hibernate 4 or above, Spring 4.1 or above and MySQL drivers. If you are using Spring 4.1, make sure to also include the latest libraries for Jackson FastXML. The conversion of Object to JSON and vice versa is handle by Jackson library and it does not work without the latest libraries.</li>
<li>If you are not using maven or gradle, make sure the following jars are in your WEB-INF/lib folder as provided in the below screenshot</li>
</ul>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><img decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/07/dependent_libraries.png" alt="Library Jars" width="404" height="710" /></p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;">The source code in the GitHub contains all required libraries.</p>
<p style="text-align: left;"><span style="text-decoration: underline;">Web.xml configuration</span></p>
<p style="text-align: left;">We configure Spring DispatcherServlet, specify the patch to Spring configuration file (if not using default path and file name) and map the request to a URL pattern. For this project, we use *.json mapping. Hence, all the request URL should have .json at the end. Note that, if you perform a partial URL mapping like /product/*, you will have to configuring the ViewResolver, so that it could use the appropriate resolvers for JSON. However, when an extension mapping like .json, no ViewResolver configuration is required.</p>
<pre class="language-markup"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"&gt;
  &lt;display-name&gt;Catalog REST Services&lt;/display-name&gt;
  &lt;welcome-file-list&gt;
    &lt;welcome-file&gt;Login.jsp&lt;/welcome-file&gt;
  &lt;/welcome-file-list&gt;
  &lt;servlet&gt;
    &lt;servlet-name&gt;CatalogServlet&lt;/servlet-name&gt;
    &lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;
    &lt;init-param&gt;
      &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
      &lt;param-value&gt;/WEB-INF/Catalog-Servlet.xml&lt;/param-value&gt;
    &lt;/init-param&gt;
    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
    &lt;servlet-name&gt;CatalogServlet&lt;/servlet-name&gt;
    &lt;url-pattern&gt;*.json&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
&lt;/web-app&gt;</code></pre>
<p style="text-align: left;"><span style="text-decoration: underline;">WEB-INF/Catalog-Servlet.xml</span></p>
<p style="text-align: left;">Most of the tags are self-explanatory. Although this is a Spring configuration, it references Hibernate related files and hibernate.cfg.xml. The &#8220;datasource&#8221; needs to be updated with your username, password and dbname. Also, note the configuration for transactionManager. Once this is configured, Spring handles the hibernate transactions and you do not have to manually manage the transaction in your code. Just mark the service method with @Transactional annotation.</p>
<p style="text-align: left;">The ProductDao and ProductService is also declared. We have marked them as @Autowired and hence we do not have to pass the reference for productDao into productService in the XML.</p>
<pre class="language-markup"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd"&gt;

	&lt;mvc:annotation-driven /&gt;
&lt;!-- Configure JDBC Connection - @TODO update url, username and password per your database configuration --&gt;
      &lt;bean id="dataSource"
            class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
            &lt;property name="driverClassName" value="com.mysql.jdbc.Driver" /&gt;
            &lt;property name="url" value="jdbc:mysql://localhost:3306/tfcom_articles" /&gt;
            &lt;property name="username" value="admin" /&gt;
            &lt;property name="password" value="admin*" /&gt;
      &lt;/bean&gt;
      
    &lt;tx:annotation-driven transaction-manager="transactionManager" /&gt;
    
     &lt;bean id="transactionManager"
            class="org.springframework.orm.hibernate4.HibernateTransactionManager"&gt;
        &lt;property name="sessionFactory" ref="sessionFactory"/&gt;
    &lt;/bean&gt;
    
      
    &lt;bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"&gt;
    &lt;property name="dataSource"&gt;
                  &lt;ref bean="dataSource" /&gt;
            &lt;/property&gt;
    &lt;property name="configLocation" value="classpath:hibernate.cfg.xml" /&gt;
	&lt;/bean&gt;
	
	&lt;context:component-scan base-package="com.tech_freaks.catalog"/&gt;
	
	&lt;bean id="productDao"
   	class="com.tech_freaks.catalog.dao.ProductDAOImpl"/&gt;
   	
   	&lt;bean id="productService"
   	class="com.tech_freaks.catalog.service.ProductServiceImpl"/&gt;
&lt;/beans&gt;</code></pre>
<pre class="brush:xml" style="color: #333333; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;"></pre>
<p style="text-align: left;"><span style="text-decoration: underline;">src/hibernate.cfg.xml</span></p>
<p style="text-align: left;">We have used the XML configuration for hibernate and not annotations. This mainly declares the Product hibernate class and its mapping file Product.hbm.xml.</p>
<p style="text-align: left;">The commented fields in this file will need to be un-commented, if you are reverse engineering the hibernate object as explained in the article <a title="Reverse Engineering Hibernate objects using JBoss eclipse plugin" href="jsp-servlets/jboss-reverse-engineer-hibernate.html" target="_blank" rel="alternate noopener noreferrer">Reverse Engineering Hibernate objects using JBoss eclipse plugin</a></p>
<hr class="system-pagebreak" title="Development" />
<p style="text-align: left;"><strong>Development</strong></p>
<p style="text-align: left;"><span style="text-decoration: underline;">Hibernate Object</span><br />
Product.java &#8211; We reverse engineer this class from the database. It is the model for the application, which is mapped to the database table. It is self-explanatory.</p>
<p style="text-align: left;"><span style="text-decoration: underline;">DAO layer</span></p>
<p style="text-align: left;"><em>AbstractDAO&lt;T&gt;</em> &#8211; This is a generic class which contains common calls to hibernate API. All DAO can extend this class to reuse these pre-implemented class. Note, how the sessionFactory is injected by Spring framework into the DAO layer using @Autowired annotation. The sessionFactory is declared in the Catalog-Servlet.xml file which we defined earlier.</p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;">The JavaDoc comments on each of the method, explain the use of the function.</p>
<pre class="language-java"><code>package com.tech_freaks.catalog.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Generic Base class which encapsulates hibernate specific calls which will be available from the 
 * extending DAO which is mapped to the database table.
 * @author Tech Freaks
 *
 * @param &lt;T&gt; - The Hibernate object which it works on
 */
public class AbstractDAO &lt;T&gt; {
	
	@Autowired
    private SessionFactory sessionFactory;
 
	/**
	 * Gets a current session from the hibernate factory
	 * @return
	 */
    protected Session getSession(){
        return sessionFactory.getCurrentSession();
    }
    
    /**
     * Generic method for finding by primary key. 
     * @param id  - Primary key value in integer
     * @param myClass - Type of Class which will be loaded
     * @return T representing instance of the loaded hibernate class instance
     */
    public &lt;T&gt;  T findById(Integer id, Class myClass) {
    	return (T) getSession().load(myClass, id);
    }
 
    /**
     * Inserts record into database
     * @param t - Instance of the Hibernate object which needs to be persisted in the db
     * @return - Key value of the newly inserted record
     */
    public Integer persist(T t) {
       return (Integer) getSession().save(t);
    }
    
    /**
     * Updates the database for provided generic type
     * @param t Generic type for the hibernate object
     */
    public void update(T t) {
    	getSession().update(t);
    	getSession().flush();
    }
     
    /**
     * Deletes the entity from the database for the provided generic type
     * @param t  Generic type for the hibernate object
     */
    public void delete(T t) {
        getSession().delete(t);
        getSession().flush();
    }
}</code></pre>
<p style="text-align: left;"><em>ProductDAOImpl &amp; ProductDAO</em><br />
This is the actual DAO interface and its implementation. It extends the AbstractDAO&lt;Product&gt; and utilizes the methods defined there.</p>
<pre class="language-java"><code>package com.tech_freaks.catalog.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.tech_freaks.catalog.model.Product;

public class ProductDAOImpl extends AbstractDAO&lt;Product&gt; implements ProductDAO {
	
	
	/**
	 * Fetches all the product from the PRODUCT table
	 */
	@Override
	public List&lt;Product&gt; getAllProducts() {
		Session session = getSession();
        List&lt;Product&gt; productList = session.createQuery("from Product").list();
        return productList;
	}
	
	/**
	 * Fetches product based on the primary key productId
	 */
	@Override
	public Product findById(Integer id) {
		return (Product) getSession().get(Product.class, id);
	}
	
	/**
	 * Inserts a new record in the product table.
	 */
	@Override
	public Integer insert(Product product) {
		return persist(product);
	}
	
	/**
	 * Loads the product using the primary key and then removes it from the database.
	 */
	@Override
	public boolean remove(Integer id)  {
		boolean deleted = false;
		Product delProduct = findById(id);
		if(delProduct!=null) {
			delete(delProduct);
			deleted = true;
		} 
		return deleted;
	}
}</code></pre>
<p style="text-align: left;"><em>ProductServiceImpl &amp; ProductService</em></p>
<p style="text-align: left;">The is the Service layer interface and its implementation for the Product manipulation. It internally calls the DAO layer. The Service layer is called from the Controller class. The methods are self-explanatory.</p>
<p style="text-align: left;">The below excerpt from ProductServiceImpl shows @Autowiring annotation on productDAO, which is injected in by the Spring framework. Also, each method is marked with annotation @Transactional. This is the reason, you do not see any code related to transaction management in the DAO layer. Spring manages the transaction code for you.</p>
<pre class="language-java"><code>...
@Autowired
	private ProductDAO productDAO;
	
	@Override
	@Transactional
	public List&lt;Product&gt; listProducts() {
		
		return productDAO.getAllProducts();
	}
...</code></pre>
<p style="text-align: left;"><em>CatalogRestController </em>is the entry point into the code for all REST service verbs. The @RestController annotation eliminates the need to mark each method with @ResponseBody when it returns an Object or a Collection of objects. Now even without @ResponseBody, when an object or collection of object is returned, it is automatically converted into JSON. The class is also marked with @RequestMapping(&#8220;/products&#8221;). This means the REST URL for every verb call will have &#8216;/products&#8217; in it, after the application context name. Now, each method is marked with @RequestMethod. We follow the REST specification by mapping GET to retrieve data, POST for insert data, PUT for update data and DELETE for deleting data.</p>
<p style="text-align: left;">If we look at the method &#8220;add&#8221;, there are certain points worth noticing.</p>
<p style="text-align: left;">First, after every REST call, we return a HttpStatusCode. If the insert is successful, we return CREATED status or 201. If it fails, because the Product object was not populated, it means, the JSON was not well formed. In this case, we return BAD_REQUEST or 400. This helps the client to read the HttpHeader in the response and take appropriate action.</p>
<p style="text-align: left;">Second, after insert, the method create a REST URL to fetching the newly inserted record. This is set in the Location HttpHeader.</p>
<p style="text-align: left;">The private method isValid() is called internally to perform some basic validation before the service layer is invoked.</p>
<p style="text-align: left;">Similarly, all the other method are developed. The complete CatalogRestController code is below.</p>
<pre class="language-java"><code>package com.tech_freaks.catalog.controller;

import java.net.URI;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import com.tech_freaks.catalog.model.Product;
import com.tech_freaks.catalog.service.ProductService;

@RestController
@RequestMapping("/products")
/**
 * Entry point for REST service calls. Different method for handling insert, update, delete and get
 */
public class CatalogRestController {

	protected final Log logger = LogFactory.getLog(getClass());

	@Autowired
	private ProductService productService;

	@RequestMapping(method = RequestMethod.GET)
	public List&lt;Product&gt; getProducts() {
		return productService.listProducts();

	}

	@RequestMapping(value = "/{productId}", method = RequestMethod.DELETE)
	public ResponseEntity&lt;?&gt; remove(@PathVariable Integer productId) {
		boolean deleted = false;
		ResponseEntity&lt;?&gt; response = null;
		try {
			deleted = productService.removeProduct(productId);
		} catch (Exception e) {
			logger.error("Error deleting product from database: "
					+ e.getMessage());
		}
		if (deleted)
			response = new ResponseEntity&lt;&gt;(HttpStatus.OK);
		else
			response = new ResponseEntity&lt;&gt;(HttpStatus.NO_CONTENT);
		return response;
	}

	@RequestMapping(value = "/{productId}", method = RequestMethod.GET)
	public ResponseEntity&lt;?&gt; getProduct(@PathVariable Integer productId) {
		ResponseEntity&lt;Product&gt; response = null;
		Product product = productService.getProduct(productId);
		if (product != null) {
			response = new ResponseEntity&lt;&gt;(product, HttpStatus.OK);
		} else {
			response = new ResponseEntity&lt;&gt;(HttpStatus.NO_CONTENT);
		}
		return response;
	}

	@RequestMapping(value = "/{productId}", method = RequestMethod.PUT)
	public ResponseEntity&lt;?&gt; update(@PathVariable Integer productId,
			@RequestBody Product input) {
		ResponseEntity&lt;?&gt; response = new ResponseEntity&lt;&gt;(HttpStatus.OK);
		logger.info("Product Id to be updated is " + productId);
		logger.info("New Product Name will be " + input.getName());
		try {
			if (productId &gt; 0 &amp;&amp; isValid(input)) {
				input.setProductId(productId);
				productService.updateProduct(input);
				response = new ResponseEntity&lt;&gt;(HttpStatus.OK);
				
			} else {
				response = new ResponseEntity&lt;&gt;(HttpStatus.BAD_REQUEST);
			}
		} catch (HibernateException he) {
			logger.error("Unable to update product in database: "+ he.getMessage());
			response = new ResponseEntity&lt;&gt;(HttpStatus.NO_CONTENT);
		} catch (Exception e) {
			logger.error("Unable to update product in database: "+ e.getMessage());
			response = new ResponseEntity&lt;&gt;(HttpStatus.BAD_REQUEST);
		}
		return response;
	}

	@RequestMapping(method = RequestMethod.POST)
	public ResponseEntity&lt;?&gt; add(@RequestBody Product input) {
		HttpHeaders httpHeaders = new HttpHeaders();
		ResponseEntity&lt;?&gt; response = null;
		if (isValid(input)) {
			logger.info("Product description is " + input.getDescription());
			try {
				Integer productId = productService.createProduct(input);
				URI location = ServletUriComponentsBuilder
						.fromCurrentServletMapping()
						.path("/products/{productId}.json").build()
						.expand(productId).toUri();
				logger.info("Location uri is " + location.toString());
				httpHeaders.setLocation(location);
				response = new ResponseEntity&lt;&gt;(null, httpHeaders,
						HttpStatus.CREATED);
			} catch (Exception e) {
				logger.error("Unable to insert new product in database: "
						+ e.getMessage());

				response = new ResponseEntity&lt;&gt;(null, httpHeaders,
						HttpStatus.UNPROCESSABLE_ENTITY);
			}
		} else {
			response = new ResponseEntity&lt;&gt;(null, httpHeaders,
					HttpStatus.BAD_REQUEST);
		}
		return response;
	}

	/*
	 * Internally used to validate the fields to make sure, all required fields
	 * are present before calling the service layer for insert
	 */
	private boolean isValid(Product product) {
		boolean valid = false;
		if (product != null) {
			if (!StringUtils.isEmpty(product.getName())
					&amp;&amp; !StringUtils.isEmpty(product.getDescription())
					&amp;&amp; !StringUtils.isEmpty(product.getPartnumber())
					&amp;&amp; !StringUtils.isEmpty(product.getName()))
				valid = true;
		}
		return valid;
	}
}</code></pre>
<p style="text-align: left;">At this point, you can download the complete project from GitHub at <a href="https://github.com/tech-freaks/catalog-service" target="_blank" rel="alternate noopener noreferrer">https://github.com/tech-freaks/catalog-service</a></p>
<hr class="system-pagebreak" title="Unit Testing" />
<p style="text-align: left;"><strong>Unit Testing</strong></p>
<p style="text-align: left;">The first part of the unit test, is to figure out the REST URL to invoke. We can figure this out, if we look at the CatalogRestController and web.xml. Remember, web.xml maps *.json to the controller. Hence, for all verbs our URL will end with .json.</p>
<p style="text-align: left;">We used the following information:</p>
<p style="text-align: left;">Tomcat host: http://localhost:8080<br />
Application Context: /catalog-service<br />
CatalogRestController mapping: /products</p>
<p style="text-align: left;">Now, the method getProducts() do not have any value mapping. But, it needs to be a GET call. Hence, for accessing this method, you will use the URL http://localhost:8080/catalog-service/products.json and it needs to be a GET call. You can therefore, just paste the URL in a browser and it will show the JSON with all products.</p>
<p style="text-align: left;">Similarly, if you look at getProduct(), the request mapping has /{productId}. This is equivalent to the primary key, product_id value in the database. Hence, the URL will be http://localhost:8080/catalog-service/products/1.json , where product_id=1. This will be again a GET verb again, as we are fetching information.</p>
<p style="text-align: left;">Now, similarly, we can figure out the remaining URL for calling remove(), update() and add(). The below table provide the remaining URL and verbs.</p>
<table style="margin-left: 0px; margin-right: auto;">
<tbody>
<tr>
<td width="120">Method</td>
<td width="540">URL</td>
<td width="120">Verb</td>
</tr>
<tr>
<td width="120">remove()</td>
<td width="540">http://localhost:8080/catalog-service/products/{productId}.json</td>
<td width="120">DELETE</td>
</tr>
<tr>
<td width="120">update()</td>
<td width="540">http://localhost:8080/catalog-service/products/{productId}.json</td>
<td width="120">PUT</td>
</tr>
<tr>
<td width="120">add()</td>
<td width="540">http://localhost:8080/catalog-service/products.json</td>
<td width="120">POST</td>
</tr>
</tbody>
</table>
<p style="text-align: left;">Where {productId} will be replaced by product_id value in the database.</p>
<p style="text-align: left;">Now, there will be two question:<br />
1. How to invoke DELETE, PUT and POST verb? When we paste the URL in the browser, they all are by default GET requests.<br />
2. How to pass the product information for add() and update()?</p>
<p style="text-align: left;">For # 1, we can download a browser plugin called as Poster (Just search Poster plugin), which is available for Chrome and Firefox. The below screenshot shows, Poster in action for Firefox.</p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/07/poster_request_response.png" alt="Poster plugin for Firefox in Action" width="870" height="867" /></p>
<p style="text-align: left;">For # 2, we need to send an input json containing the product information to be insert or updated in the product table. The POST performs and insert, while PUT updates. The json format is exactly as the response received from http://localhost:8080/catalog-service/products/{productId}.json GET verb. However, we have provided an input file by the name POST_PUT_Input.json, which is in the root folder of the project.</p>
<p style="text-align: left;">In Poster plugin, you need to make sure, that to add a Header by the name &#8220;Content-Type&#8221; with value &#8220;application/json&#8221;.</p>
<p style="text-align: left;">For integration testing, we generally run the client code like the mobile application in same network and point to the URLs provided above. However, integration testing is beyond the scope of this article.</p>
<p style="text-align: left;">This completes the workshop for creating a simple product REST service using Spring MVC 4.</p>
<p style="text-align: left;">Happy RESTing!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-freaks.com/java/jsp-servlets/rest-service-spring-hibernate.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Quick Tomcat and Eclipse Integration  Deploying Web apps to Tomcat from within Eclipse</title>
		<link>https://www.tech-freaks.com/java/jsp-servlets/quick-eclipse-tomcat-integration.html</link>
					<comments>https://www.tech-freaks.com/java/jsp-servlets/quick-eclipse-tomcat-integration.html#respond</comments>
		
		<dc:creator><![CDATA[Tech Programmer]]></dc:creator>
		<pubDate>Fri, 26 Jun 2015 19:31:31 +0000</pubDate>
				<category><![CDATA[JSP & Servlets]]></category>
		<guid isPermaLink="false">http://localhost/tfcom_wp/2015/06/26/quick-eclipse-tomcat-integration/</guid>

					<description><![CDATA[Overview When you are working on a web application development using Tomcat server and Eclipse IDE, it could be painful [&#8230;]]]></description>
										<content:encoded><![CDATA[		<div class="wpulike wpulike-default " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="15"
					data-ulike-nonce="cf6922c48c"
					data-ulike-type="post"
					data-ulike-template="wpulike-default"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_15"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p style="text-align: left;"><strong><span style="font-size: 12pt;">Overview</span></strong></p>
<p style="text-align: left;">When you are working on a web application development using Tomcat server and Eclipse IDE, it could be painful and inefficient to create a WAR file and deploy to Tomcat after every code change. There are multiple ways to make the development process efficient.</p>
<ol style="text-align: left;">
<li>Create Tomcat Server within Eclipse</li>
<li>Create Ant or other build script to deploy to Tomcat webapps folder</li>
<li>Setup your Eclipse project to be within Tomcat/webapps folder</li>
</ol>
<p style="text-align: left;">The simplest and most convenient is the creating a Tomcat Server within Eclipse. This article walks through the steps to configure Tomcat to run from within Eclipse.</p>
<p style="text-align: left;">This article uses Eclipse Kepler and Tomcat 8, but the process should be similar with other versions too.</p>
<p style="text-align: left;">The article does not walk through JDK, Tomcat and Eclipse installation.</p>
<p style="text-align: left;"><strong><span style="font-size: 12pt;">Steps</span></strong></p>
<ol style="text-align: left;">
<li>Download and install Java JDK 7 or later from Oracle website: <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank" rel="author noopener noreferrer">http://www.oracle.com/technetwork/java/javase/downloads/index.html</a></li>
<li>Download and install Tomcat 8 from Apache website: <a href="https://tomcat.apache.org/download-80.cgi" target="_blank" rel="alternate noopener noreferrer">https://tomcat.apache.org/download-80.cgi</a></li>
</ol>
<ol style="list-style-type: lower-alpha; text-align: left;" start="4">
<li>Download Eclipse for JEE developer from Eclipse website: <a href="http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/keplersr1" target="_blank" rel="alternate noopener noreferrer">http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/keplersr1</a></li>
<li>Follow the URL <a href="https://wiki.eclipse.org/JDT/Eclipse_Java_8_Support_For_Kepler" target="_blank" rel="alternate noopener noreferrer">https://wiki.eclipse.org/JDT/Eclipse_Java_8_Support_For_Kepler</a> if you installed JDK 8 and want Eclipse to support JDK 8</li>
<li><strong>Creating Tomcat 8 server in Eclipse</strong></li>
</ol>
<p style="text-align: left;">a. Open Java EE perspective and access the Server tab below. You should see as the below screenshot</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/no_server_defined.png" alt="No Server Defined" width="1519" height="817" /></p>
<p style="text-align: left;">b. Click the link to create new Server as highlighted in screen above.</p>
<p style="text-align: left;">c. In the window that opens, click Apache and check for Tomcat 8. If you do not see, Tomcat 8 option perform the steps d to e.</p>
<p style="text-align: left;">d. Go to Help -&gt; Install New Software..</p>
<p style="text-align: left;">e. In the window that opens, enter the URL as &#8211; http://download.eclipse.org/webtools/repository/luna</p>
<p style="text-align: left;"> &gt;&gt; Under the Web Tools Platform (WTP) 3.6.0, select options &#8220;JST Server Adapters&#8221; and &#8220;JST Server Adapters Extensions&#8221;. Click Next and then Accept the license agreement and finish installation.</p>
<p style="text-align: left;"> &gt;&gt; Eclipse will prompt to restart and after restarting, you should be able to Tomcat 8 option</p>
<p style="text-align: left;"> <img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/define_new_server.png" alt="Define a new server" width="932" height="851" /></p>
<p style="text-align: left;">f. Now select Tomcat 8 and click next</p>
<p style="text-align: left;">g. In the next screen, select the location of Tomcat Installation and also JDK, as shown below</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/specify_tc_install_directory.png" alt="Tomcat and JDK installation path" width="932" height="851" /></p>
<p style="text-align: left;">h. Click next and you should see the option to add your web application. Add a test application, if you have one and click finish.</p>
<p style="text-align: left;">i. You should see the new Tomcat 8 server and displayed in the Server window as shown below</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/new_tomcat8_server.png" alt="New Tomcat 8 Server" width="1519" height="817" /></p>
<p style="text-align: left;">j. Double click the new Server definition and in the file which opens in Eclipse make the settings as highlighted in the below screen. The selected option uses the Tomcat installation path to work with, instead of create a separate set of files in the user folder. If you do not want Eclipse to work on the installation folder of Tomcat, you might want to select the first option &#8216;Use Workspace Metadata&#8217;.</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/server_config_update.png" alt="Tomcat Server Configuration" width="1519" height="817" /></p>
<p style="text-align: left;">k. Next right click and Server and click Start. This should start your Tomcat server without any errors, in the Console.</p>
<p style="text-align: left;">l. Verify the Tomcat server by access the URL http://localhost:8080 and you should be able to see Tomcat screen.</p>
<p style="text-align: left;">This concludes the walk-through of configuring Tomcat to be access from within Eclipse IDE. Enjoy developing, deploying and testing on your development environment completely from within Eclipse !</p>
<blockquote>
<p style="text-align: left;">If you notice error while starting Tomcat which says &#8220;Access Denied&#8221;, it means that Eclipse is not having permission to access file in the Tomcat installation folder. You can resolve this by giving required permission to the Tomcat installation folder or by running your Eclipse as Administrator. You can also use the option &#8216;Use Workspace Metadata&#8217;, in step j, if you are unable to resolve the access issue.</p>
</blockquote>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-freaks.com/java/jsp-servlets/quick-eclipse-tomcat-integration.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Reverse Engineering Hibernate objects using JBoss eclipse plugin</title>
		<link>https://www.tech-freaks.com/java/jsp-servlets/reverse-engineer-hibernate-objects.html</link>
					<comments>https://www.tech-freaks.com/java/jsp-servlets/reverse-engineer-hibernate-objects.html#respond</comments>
		
		<dc:creator><![CDATA[Tech Programmer]]></dc:creator>
		<pubDate>Wed, 24 Jun 2015 09:09:35 +0000</pubDate>
				<category><![CDATA[JSP & Servlets]]></category>
		<guid isPermaLink="false">http://localhost/tfcom_wp/2015/06/24/reverse-engineer-hibernate-objects/</guid>

					<description><![CDATA[Writing hibernate class and xmls can be a pain, especially, if you have tons of tables in your database. One [&#8230;]]]></description>
										<content:encoded><![CDATA[		<div class="wpulike wpulike-default " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="29"
					data-ulike-nonce="4ba46d0a73"
					data-ulike-type="post"
					data-ulike-template="wpulike-default"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_29"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p style="text-align: left;">Writing hibernate class and xmls can be a pain, especially, if you have tons of tables in your database. One way to alleviate the pain is to use a reverse engineering tool, which would generate the xml and java files for hibernate by connecting to database. This article walks through the steps from installing the JBoss Tools Eclipse plugin to generate hibernate java and xml files.</p>
<p><strong><span style="font-size: 12pt;">Pre-requisites </span></strong></p>
<ul>
<li style="text-align: left;">MySQL and Eclipse are installed</li>
<li style="text-align: left;">MySQL has a database with at least one table</li>
<li style="text-align: left;">You have some basic knowledge about hibernate or any other ORM tool</li>
</ul>
<p style="text-align: left;"><strong><span style="font-size: 12pt;">Steps</span></strong></p>
<p style="text-align: left;"><span style="text-decoration: underline;">Installing JBoss Eclipse Tools from marketplace</span></p>
<p>Open Eclipse and follow the menu, Help -&gt; Eclipse Marketplace..</p>
<p style="text-align: left;">Search for &#8216;JBoss&#8217; or &#8216;Hibernate&#8217; and click install on the Jboss Tools</p>
<p><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/eclipse_marketplace_jboss.png" alt="Eclipse Market Place" width="700" height="921" /></p>
<p>Un-select all options except &#8220;Hibernate Tools&#8221; as shown in the below screenshot</p>
<p><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/jboss_hibernate_tools.png" alt="JBoss tools install for Eclipse" width="700" height="921" /></p>
<p>Click &#8220;Confirm&#8221; and then &#8220;Finish&#8221;. Accept the license agreement.</p>
<p>Eclipse will prompt to restart</p>
<p style="text-align: left;"><span style="text-decoration: underline;">Creating the hibernate configuration (hibernate.cfg.xml)</span></p>
<p>Once Eclipse has restarted, Open hibernate perspective. Windows -&gt; Open Perspective -&gt; Others</p>
<p><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/open_hibernate_perspective.png" alt="Open Hibernate Perspective" width="371" height="474" /></p>
<p>The perspective will be empty. Click on the &#8220;Add Configuration&#8221; to start the configuration process, as shown below</p>
<p><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/hibernate_configurations.png" alt="Hibernate Configurations" width="1519" height="817" /></p>
<p>A window &#8220;Edit Configuration&#8221; will show up, as per the below screen shot. Select the Project by clicking Browse.</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/hibernate_edit_config.png" alt="Hibernate Edit Configuration" width="700" height="702" /></p>
<p>Next, click &#8220;Setup&#8221; from Configuration File section. This will open another windows as shown below.</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/create_cfg_xml.png" alt="Create hibernate.cfg.xml" width="868" height="779" /></p>
<p style="text-align: left;">Using this, we will be creating the hibernate.cfg.xml which has the information like the database dialect, database URL, drivers, database type, db user id and db password. Once you click &#8220;Finish&#8221;, this will generate the hibernate.cfg.xml. Then click the &#8220;OK&#8221; in the &#8220;Edit Configuration&#8221; window should be open.</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/rebuild_config.png" alt="Rebuild Hibernate Config" width="1519" height="855" /></p>
<p>Next, go to the Hibernate Configuration in the Hibernate perspective. Right click the new configuration which you added now and click &#8220;Rebuild Configuration&#8221;. You should now check the section under &#8220;Database&#8221; in the hibernate configuration.  You should see the tables from your database. If the tables are not showing and it shows an error, you should not proceed further and resolve this issue first. Below are some possible reasons for the error</p>
<ul>
<li style="text-align: left;">Database drivers are not in classpath:  <span style="text-decoration: underline;">Resolution</span>: Put the driver jar file in the WEB-INF/lib folder to resolve this.</li>
<li style="text-align: left;">Database service is not started: <span style="text-decoration: underline;">Resolution</span>: Start your database and try connecting again.<br />
One or more information entered in the hibernate.cfg.xml is incorrect. Verify all the information entered in the hibernate.cfg.xml, anything which is incorrect.</li>
<li style="text-align: left;">If you resolved the issue as explained above, you might want to &#8220;Rebuild Configuration&#8221; after resolving the issue.Once you can see the Database tables, you can proceed to the reverse engineering steps provided below.
<p><span style="text-decoration: underline;">Create a new Hibernate Reverse Engineering file</span></p>
<p>From the Hibernate Perspective click &#8220;File&#8221; -&gt; &#8220;New&#8221; -&gt; &#8220;Hibernate Reverse Engineering File (reveng.xml)&#8221;</li>
</ul>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/reveng_xml_step1.png" alt="Create the reverse engineering file" width="700" height="671" /><br />
In the Wizard that opens, select the project and click &#8220;Next&#8221;</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/reveng_xml_step2.png" alt="Reverse Engineering Step 2" width="700" height="671" /></p>
<p>Select the &#8220;Console Configuration&#8221; from the drop down in the next step and click the &#8220;Refresh&#8221; button. The Database Schema section will show your database and tables. Select all the tables and click include. Click the &#8220;Finish&#8221; button to generate hibernate.reveng.xml file.</p>
<blockquote><p>If you are unable to generate the hibernate objects, check that you have included all individual tables instead of the whole database and re-generate the reveng.xml</p></blockquote>
<p style="text-align: left;">Once you have the reverse engineering file generated, you need to do Run -&gt; Hibernate Code Generation -&gt; Hibernate Code Generation Configurationâ‚¬¦</p>
<p><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/hibernate_code_generation_config.png" alt="Hibernate Code Generation Configuration" width="1519" height="855" /></p>
<p>In the window that opens, create a new configuration and enter details as per the below screenshot and click &#8220;Run&#8221;.</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/hibernate_code_generation_config_main.png" alt="Hibernate code generation main tab" width="906" height="702" /></p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/hibernate_code_generation_config_exporters.png" alt="Hibernate code generation exporters" width="906" height="702" /></p>
<p>Go back to Java EE perspective and you will see the hibernate xmls and java files generated in the package specified in the Main tab of the configuration before clicking Run.</p>
<p>You might want to modify some of the content in the xml or java files generated as per your needs. However, remember that, if you have to regenerated the hibernate objects, your manual changes might get lost.</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" src="https://www.tech-freaks.com/wp-content/uploads/2015/06/add_mapping_cfg.png" alt="Add Mapping to hibernate.cfg.xml" width="1519" height="817" /><br />
One last step you would need to perform, is to add the mapping of the bean in the hibernate.cfg.xml. Below shows a screenshot of adding one mapping.</p>
<p style="text-align: left;">That completes the steps to reverse engineer hibernate objects using JBoss Tools in Eclipse.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-freaks.com/java/jsp-servlets/reverse-engineer-hibernate-objects.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Simple Login Application using Struts 2</title>
		<link>https://www.tech-freaks.com/java/jsp-servlets/struts2-login-application.html</link>
					<comments>https://www.tech-freaks.com/java/jsp-servlets/struts2-login-application.html#respond</comments>
		
		<dc:creator><![CDATA[Tech Programmer]]></dc:creator>
		<pubDate>Thu, 28 May 2015 22:10:38 +0000</pubDate>
				<category><![CDATA[JSP & Servlets]]></category>
		<guid isPermaLink="false">http://localhost/tfcom_wp/2015/05/28/struts2-login-application/</guid>

					<description><![CDATA[Requirement Create a Login page to enter user name and password On submit, validate the user name / password against [&#8230;]]]></description>
										<content:encoded><![CDATA[		<div class="wpulike wpulike-default " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="30"
					data-ulike-nonce="8653e9fd4f"
					data-ulike-type="post"
					data-ulike-template="wpulike-default"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_30"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p><strong>Requirement</strong></p>
<ul style="text-align: left;">
<li>Create a Login page to enter user name and password</li>
<li>On submit, validate the user name / password against MySQL database</li>
<li>If the authentication is successful, forward to home page showing welcome message along with the user name</li>
<li>If the authentication fails, return back to the login page with appropriate error message</li>
<li>If there is exception / errors during authentication process return back to login page with appropriate error message.</li>
</ul>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span style="font-size: 12pt;"><strong>Pre-requisites</strong></span></p>
<ul style="text-align: left;">
<li>MySQL and Tomcat is already installed</li>
<li>MySQL is setup with database and tables for use. Refer<span class="Apple-converted-space"> </span><a style="color: #1b57b1; text-decoration: none; font-weight: normal;" href="jsp-servlets/simple-login-application.html" target="_blank" rel="alternate noopener noreferrer">Simple Login Application</a> for details</li>
<li>You have basic knowledge of Java and J2EE web applications</li>
<li>Basic idea about Struts 1 or 2 or at least about MVC design</li>
</ul>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span style="font-size: 12pt;"><strong>Concepts Covered</strong></span></p>
<ul style="text-align: left;">
<li>IDE set up for Struts 2</li>
<li>Struts2 key components</li>
<li>Difference between struts 1 and struts 2 highlighted</li>
</ul>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;"><span style="font-size: 12pt;"><strong>Environment Setup</strong></span></p>
<ul style="text-align: left;">
<li>Download Eclipse for Java EE which is all ready to go with JEE features and install it. Download from <a href="https://eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/lunar" rel="alternate noopener" target="_blank">Eclipse for JEE Download</a></li>
<li>Create a &#8220;Dynamic Web Project&#8221; in eclipse with the name Struts2LoginApp.<br />
Click next, then next and finish.</li>
<li>Download latest Struts2 binaries from <a title="Struts 2 Binaries Download" href="https://struts.apache.org/download.cgi" target="_blank" rel="alternate noopener noreferrer">Struts 2 Binaries Download</a>. At the time of writing this article, struts 2.3.24 was used.</li>
<li>Unzip the binaries and copy the following JAR files to the lib directory(&lt;workspace&gt;\Struts2LoginApp\WebContent\WEB-INF\lib) of the newly created project:</li>
</ul>
<p style="padding-left: 30px; text-align: left;">commons-fileupload-1.3.1.jar<br />
commons-io-2.2.jar<br />
commons-lang3-3.2.jar<br />
commons-logging-1.1.3.jar<br />
commons-logging-api-1.1.jar<br />
freemarker-2.3.22.jar<br />
javassist-3.11.0.GA.jar<br />
ognl-3.0.6.jar<br />
struts2-core-2.3.24.jar<br />
xwork-core-2.3.24.jar</p>
<p style="padding-left: 30px; text-align: left;">Since we make connections to MySQL using JDBC, we would also need to put the JAR for the MySQL JDBC driver (mysql-connector-java-5.1.20-bin.jar). You can download the latest version of the jar from<span class="Apple-converted-space"> </span><a style="color: #1b57b1; text-decoration: none; font-weight: normal;" title="MySQL JDBC Driver Download" href="http://dev.mysql.com/downloads/connector/j/" target="_blank" rel="alternate noopener noreferrer">MySQL JDBC Driver Download</a>.</p>
<p style="padding-left: 30px; text-align: left;"><strong>web.xml configuration:</strong><br />
A blank web.xml might have been added to your project under WEB-INF folder. This file is the JSP deployment descriptor. We need to configure the struts 2 controller, which is a servlet filter by the name FilterDispatcher. If you are familiar with Struts1, you will recollect that in the web.xml, we used to make an entry for the ActionServlet which was the controller in struts1.</p>
<pre class="language-markup"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee" 
   xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0"&gt;
   
   &lt;display-name&gt;Struts 2 Login App&lt;/display-name&gt;
   &lt;welcome-file-list&gt;
      &lt;welcome-file&gt;Login.jsp&lt;/welcome-file&gt;
   &lt;/welcome-file-list&gt;
   &lt;filter&gt;
      &lt;filter-name&gt;struts2&lt;/filter-name&gt;
      &lt;filter-class&gt;
         org.apache.struts2.dispatcher.FilterDispatcher
      &lt;/filter-class&gt;
   &lt;/filter&gt;

   &lt;filter-mapping&gt;
      &lt;filter-name&gt;struts2&lt;/filter-name&gt;
      &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
   &lt;/filter-mapping&gt;
&lt;/web-app&gt;</code></pre>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;"><span style="font-size: 12pt;"><strong>Analysis and Design</strong></span></p>
<p style="text-align: left;">If you do not have the database table created or do not have any user in that table, please refer the analysis and design from the article <a href="jsp-servlets/simple-login-application.html" target="_blank" rel="alternate noopener noreferrer">Simple Login Application</a> for details.</p>
<p style="text-align: left;">Taking inspiration from the previous article, we will create similar components for our simple login app using struts 2.</p>
<p style="text-align: left;">So, below are the identified components:</p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;"><span style="font-size: 10pt;">Login.jsp</span><br />
<span style="font-size: 10pt;">Home.jsp</span><br />
<span style="font-size: 10pt;">LogonAction.java</span></p>
<p style="padding-left: 30px; text-align: left;">Let us look at each identified component and its role in our application:</p>
<ul style="text-align: left;">
<li>Login.jsp -&gt; It would present the login screen to enter user id and password. It also displays any validation errors and login failure message.</li>
<li>Home.jsp -&gt; Simple JSP which displays a welcome message after successful login</li>
<li>com.tech_freaks.action.LogonAction.java<br />
While we take inspiration from LogonServlet of our previous example, we improve the design to not include any database connectivity code in our Action class. To achieve this, we will refactor all the DB access / calls to a Helper class by the name DBHelper.java. This also helps in modifying the code, if we tomorrow decide to use Entity Beans (EJB) or hibernate to access the database instead of raw JDBC code with minimum impact on our Action class. The LogonAction performs the following tasks.<br />
&#8211; Perform basic empty check on server side before calling the database<br />
&#8211; Call our DB Helper class, with user name and password to check, if the combination exists.</li>
<li>com.tech_freaks.utils.DBHelper.java<br />
It will perform all task related to getting connection to the DB, executing a query and method to return Boolean indicating, if record was available or not in the DB. We do not write method like, isUserPasswordValid in this class, as it is a generic low level class, and should not be aware about the logic implemented in the classes calling it. Below would be the methods:</li>
</ul>
<p style="padding-left: 40px; text-align: left;"><em>public boolean containsResults(String query, String[] params) </em>-&gt; The params we have created as a String array, which will have both user name and password. If the values required for the where clause of the SQL query are of different datatype, we might need a different approach. This method is invoked by the LogonAction</p>
<p style="padding-left: 40px; text-align: left;"><em>private Connection getConnection()</em> -&gt; Internally used to get a Connection object for the DB call.</p>
<p style="padding-left: 40px; text-align: left;"><em>private void closeConnection(Connection conn)</em> &#8211; Closes an open connection after the query has been executed.</p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;"><span style="font-size: 12pt;"><strong>Development</strong></span></p>
<p style="text-align: left;">We will first start by adding a struts.xml for our project. In eclipse, you will have to create a folder &#8216;classes&#8217; under \workspace\Struts2LoginApp\WebContent\WEB-INF\ and add struts.xml in that folder.</p>
<p style="text-align: left;">Below is the struts.xml</p>
<pre class="language-markup"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd"&gt;
&lt;struts&gt;
&lt;constant name="struts.devMode" value="true" /&gt;
   &lt;package name="loginapp" extends="struts-default"&gt;
     
      &lt;action name="logon" 
            class="com.tech_freaks.action.LogonAction" 
            method="execute"&gt;
            &lt;result name="success"&gt;/Home.jsp&lt;/result&gt;
            &lt;result name="input"&gt;/Login.jsp&lt;/result&gt;
            &lt;result name="error"&gt;/Login.jsp&lt;/result&gt;
      &lt;/action&gt;
   &lt;/package&gt;
&lt;/struts&gt;</code></pre>
<p style="text-align: left;"> The configuration file is straightforward and easy to understand. &lt;constant&gt; is setting the project in a development mode. This will give helpful errors in the logs / screen while debugging issues.</p>
<p style="text-align: left;">&lt;package&gt; is applicable when we divide the configure into multiple logical parts instead of having all action definition inside single file.<br />
Let us take a careful look at the entry for &lt;action&gt; and ensure all mapping components are named to match the entries in here.</p>
<p style="padding-left: 30px; text-align: left;">â‚¬¢ â‚¬Å“nameâ‚¬ attribute needs to be mapped to the &lt;form action=â‚¬â‚¬&gt; in the Login.jsp. This is how struts knows which Action class to invoke. We leave the method to â‚¬Å“executeâ‚¬ as our Action class will extend ActionSupport class and override the execute method.<br />
â‚¬¢ â‚¬Å“classâ‚¬ should be fully qualified class name of the Action class.<br />
â‚¬¢ When the Action executes, we can configure different JSPs / views to invoke after completion. The String value returned from Action.execute() method should match the â‚¬Å“nameâ‚¬ attribute in one of the â‚¬Å“resultâ‚¬. However, it is important to note that, if we are using struts validation framework, we need to have an &lt;result&gt; with<span class="Apple-converted-space"> </span><strong>name=â‚¬inputâ‚¬</strong>. The framework will redirect to the view configured for &lt;result&gt; name=&#8221;input&#8221; with the error message. If you do not have entry for â‚¬Å“inputâ‚¬ you will see an error saying that â‚¬Å“No result defined for action and result input &#8211; action â‚¬â€œâ‚¬Å“</p>
<p style="text-align: left;">Next, we take a look at the LogonAction.java.<br />
As we plan to validate for empty fields, we need to extend the ActionSupport class. Once extended, we need to override the methods execute() and validate(). The next thing is we need to have instance variables for user fields in the Login.jsp. Note that the instance variable (mainly the getter/ setters for the instance variables) must match exactly to the â‚¬Å“nameâ‚¬ attribute on the &lt;input&gt; fields on the JSP. This is also a difference between struts 1.1 were we had separate ActionForms which had the fields mapped to the &lt;input&gt;.<br />
The complete java code is below</p>
<pre class="language-java"><code> package com.tech_freaks.action;

import java.util.HashMap;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
import com.tech_freaks.utils.DBHelper;

public class LogonAction extends ActionSupport {
	
	public static final String LOGIN_SUCCESS = "success";
	public static final String LOGIN_FAILED = "error";
	
	private static final String LOGIN_QUERY = "select * from users where user_name=? and password=?";
	
	private String userName;
	private String password;

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public String execute() throws Exception {
		ValueStack stack = ActionContext.getContext().getValueStack();
		String[] params = new String[] {userName, password};
		DBHelper dbHelper = new DBHelper();
		
		boolean isSuccess = dbHelper.containsResult(LOGIN_QUERY, params);
		if(isSuccess)
			return LOGIN_SUCCESS;
		else {
			Map&lt;String, Object&gt; context = new HashMap&lt;String, Object&gt;();
			context.put("errorMsg", new String("Invalid user name or password. Try again.")); 
			stack.push(context);
			return LOGIN_FAILED;
		}
	}

	@Override
	public void validate() {
		 if (userName == null || userName.trim().equals(""))
	      {
	         addFieldError("userName","Please enter a user name to login with.");
	      }
		 if (password == null || password.trim().equals(""))
	      {
	         addFieldError("password","Please enter a password.");
	      }
	}
}
 </code></pre>
<pre class="brush:java" style="color: #333333; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;"></pre>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;">Let&#8221;s take a close look at<span class="Apple-converted-space"> </span><em>validate()</em>. Use the<strong><span class="Apple-converted-space"> </span>addFieldError()</strong><span class="Apple-converted-space"> </span>method with the first parameter matching the field name which has the validation error. Again, this name needs to exactly match with &lt;input&gt; name attribute in the JSP. If we use the struts taglib in the JSP, it also takes care of showing the error message for each field inline to the field.</p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;">Next, we take a look at the<em><span class="Apple-converted-space"> </span>execute()</em><span class="Apple-converted-space"> </span>method. It is fairly straightforward. It calls the DBHelper class to verify in the database, if a record exists for the supplied userName and password combination. Based on the result, it returns â‚¬Å“successâ‚¬ or â‚¬Å“errorâ‚¬. The value returned needs to match with the &lt;result&gt; name attribute defined in the struts.xml which we examined before. The appropriate view will be displayed.</p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;">For the failed login attempt, we have to go back to the login page and display an error message. We use this requirement to explain<span class="Apple-converted-space"> </span><strong>ActionContext</strong><span class="Apple-converted-space"> </span>and <strong>ValueStack </strong>concept in struts 2. The ActionContext has access to variables like session, request params etc. It also contains a value stack. You can put objects into value stack. As the name suggests, it is a stack with push, pop, peek methods in it. In the JSP, when you want to access the variables in the ActionContext using the struts taglib, you use #&lt;attribute&gt; say #session. However, for accessing value stack, we do not have to use the #. As you can see, we are pushing a Map with key<span class="Apple-converted-space"> </span><em>errorMsg</em><span class="Apple-converted-space"> </span>into the value stack, with value containing the error message which needs to be displayed to the user on failed login attempt.</p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;"><strong>Login.jsp</strong><br />
This page is modified from our previous version of Login.jsp. The main change is the struts taglib usage. We use the &lt;s:property&gt; to pull the attribute from the value stack which we previously discussed. This is used where the login attempt fails. We have used &lt;s:form&gt;, &lt;s:textfield&gt; etc. They help giving inline errors for each field as per the login in the validate() method.</p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;">Below is the complete Login.jsp</p>
<pre class="language-markup"><code>&lt;%@ page language="java" contentType="text/html; charset=ISO-8859-1"
   pageEncoding="ISO-8859-1"%&gt;
&lt;%@ taglib prefix="s" uri="/struts-tags"%&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;
Tech-freaks.com - Struts2 - SimpleLogin App Login Page
&lt;/title&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;s:property value="errorMsg"/&gt;&lt;br/&gt;
&lt;s:form method="POST" action="logon"&gt;
	&lt;s:textfield  name="userName" label="User Name"/&gt;
	&lt;s:password  name="password" label="Password" /&gt;
	&lt;s:submit name="submit" label="Submit" align="center" /&gt;
		
&lt;/s:form&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;"><strong>Home.jsp</strong><br />
Simple page, which when requested due to successful login, fetches the â‚¬Å“usernameâ‚¬ field and displays the welcome message. Below is the complete JSP</p>
<pre class="language-markup"><code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;&lt;%@page
	language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%&gt;
&lt;%@ taglib prefix="s" uri="/struts-tags"%&gt;
&lt;html&gt;
	&lt;head&gt;
		&lt;title&gt;
		Tech-freaks.com - Struts 2 SimpleLogin App Home Page
		&lt;/title&gt;
		&lt;meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"&gt;
	&lt;/head&gt;
	&lt;body&gt;
	 	&lt;h1&gt; Welcome to Tech-freaks.com - Struts2 Simple Logon App, &lt;s:property value="userName"/&gt;&lt;/h1&gt;
	&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;"><strong><span style="font-size: 12pt;">Testing</span></strong></p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;">Once you have all the components put in, right click the project in Eclipse and Export as WAR. Drop the generated WAR in &lt;Tomcat&gt;\webapps folder and start Tomcat. Verify Tomcat logs, if the deployment of the WAR was successful.<span class="Apple-converted-space"> </span><br />
Test by accessing the URL : http://localhost:8080/Struts2LoginApp/Login.jsp (Modify the port and context name as per your customization)<br />
Run and verify each scenario mentioned in the requirement.</p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;"><strong>Congratulations, on completing your first &#8220;Non-Hello World&#8221; project using struts 2!</strong></p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;">You can download the complete Eclipse project from Github by clicking the link below.</p>
<p style="color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: left;"><a style="color: #1b57b1; text-decoration: none; font-weight: normal;" title="Download complete Struts 2 Login App Source code from Github" href="https://github.com/tech-freaks/struts2-login-app" target="_blank" rel="alternate noopener noreferrer">Download complete Struts 2 Login App Source code from Github</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-freaks.com/java/jsp-servlets/struts2-login-application.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Simple Registration Application using JSP, Servlets and JDBC connectivity to MySQL</title>
		<link>https://www.tech-freaks.com/java/jsp-servlets/simple-registration-application.html</link>
					<comments>https://www.tech-freaks.com/java/jsp-servlets/simple-registration-application.html#respond</comments>
		
		<dc:creator><![CDATA[Tech Programmer]]></dc:creator>
		<pubDate>Mon, 18 Feb 2013 03:58:34 +0000</pubDate>
				<category><![CDATA[JSP & Servlets]]></category>
		<guid isPermaLink="false">http://localhost/tfcom_wp/2013/02/18/simple-registration-application/</guid>

					<description><![CDATA[Requirement Create a Registration Form to enter user name, password, first name, last name, email address, secret question, answer and [&#8230;]]]></description>
										<content:encoded><![CDATA[		<div class="wpulike wpulike-default " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="32"
					data-ulike-nonce="e3e768dc91"
					data-ulike-type="post"
					data-ulike-template="wpulike-default"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_32"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p style="text-align: left;"><strong>Requirement</strong></p>
<ul style="text-align: left;">
<li><span style="line-height: 1.3em;">Create a Registration Form to enter user name, password, first name, last name, email address, secret question, answer and register a new user to system.</span></li>
<li><span style="line-height: 1.3em;">Validate if the user name and password is not blank. Display error message to user, if either of them is blank.</span></li>
<li><span style="line-height: 1.3em;">Validate if the user name already exists and display an error message to the user</span></li>
<li><span style="line-height: 1.3em;">In the event of an error, ensure that registration form is displayed again with all prefilled information</span></li>
<li><span style="line-height: 1.3em;">On successful registration, set the user name in session and forward to home page.</span></li>
</ul>
<p style="text-align: left;"><strong style="line-height: 1.3em;">Pre-requisites</strong></p>
<ul style="text-align: left;">
<li><span style="line-height: 1.3em;">MySQL and Tomcat is already installed</span></li>
<li><span style="line-height: 1.3em;">You have basic knowledge of MySQL to create tables and insert / update records</span></li>
<li><span style="line-height: 1.3em;">You have basic knowledge of Java and J2EE web applications</span></li>
<li><span style="line-height: 1.3em;">Have your favorite IDE for developing / reviewing code</span></li>
<li><span style="line-height: 1.3em;">This workshop adds the registration functionality to the previous article <a title="Simple Login Application" href="java/jsp-servlets/simple-login-application.html" target="_blank" rel="noopener noreferrer">Simple Login Application</a>. Reviewing that article prior to this article would help.</span></li>
</ul>
<p style="text-align: left;"><strong style="line-height: 1.3em;">Concepts Covered</strong></p>
<ul style="text-align: left;">
<li><span style="line-height: 1.3em;">JDBC connectivity to MySQL from Servlet</span></li>
<li><span style="line-height: 1.3em;">Simple application of JSTL tag</span></li>
<li><span style="line-height: 1.3em;">Using request attribute and request parameters</span></li>
<li><span style="line-height: 1.3em;">Basic error handling concepts</span></li>
</ul>
<p style="text-align: left;"><strong>NOTE</strong>: Don&#8217;t even think of using the code as is for a production environment<br />
This is just for education purpose but you can take inspiration from this code.</p>
<p><span id="more-32"></span></p>
<p style="text-align: left;"><strong>Analysis and Design</strong></p>
<p style="text-align: left;"><span style="line-height: 1.3em;">We start with the <a title="Simple Login Application" href="jsp-servlets/simple-login-application.html" target="_blank" rel="noopener noreferrer">Simple Login application</a> article as a baseline. First, we need to update the database to add more fields and constraints. We will make the user_name field as the primary key for the USERS table.</span></p>
<p style="text-align: left;"><span style="line-height: 1.3em;">We create a new class for database connectivity code unlike in the simple login application and refactor the connectivity code out of the Servlet code. This is a good design practice to keep the servlet layer uncoupled to the database code layer. We would still following the MVC design model.</span></p>
<p style="text-align: left;"><span style="line-height: 1.3em;">Below is a list of elements identified as part of the design:</span></p>
<ul style="text-align: left;">
<li><span style="line-height: 1.3em;"><em>com.techfreaks.db.util.ConnectionUtil</em> &#8211; Utility class for getting connection, closing connection and executing insert / update query</span></li>
<li><span style="line-height: 1.3em;"><em>com.techfreaks.registration.servlet.RegistrationServlet</em> &#8211; This servlet is the controller. It calls the ConnectionUtil and forwards to the home page or Registration page</span></li>
<li><span style="line-height: 1.3em;"><em>RegistrationForm.jsp</em> &#8211; UI page with fields for registration form</span></li>
<li><span style="line-height: 1.3em;"><em>Home.jsp</em> &#8211; UI page picked up after successful registration. It is the same page taken from Login Application</span></li>
<li><span style="line-height: 1.3em;"><em>web.xml</em> &#8211; Deployment Descriptor in which the servlet is registered.</span></li>
</ul>
<p style="text-align: left;"><strong style="line-height: 1.3em;">Development</strong></p>
<p style="text-align: left;"><em>Setup the database:</em></p>
<p style="text-align: left;">We alter the USERS table to add the new fields. However, for quick reference we provide the create USERS table DDL. You will have to drop and recreate the table using the below DML, if you already have an USER table. You could very well manually edit the existing table based on the below DDL.</p>
<pre class="brush:sql" style="text-align: left;">CREATE TABLE `users` (
	`first_name` VARCHAR(100) NOT NULL,
	`last_name` VARCHAR(100) NOT NULL,
	`email_address` VARCHAR(50) NOT NULL,
	`secret_question` VARCHAR(200) NULL DEFAULT NULL,
	`secret_answer` VARCHAR(200) NULL DEFAULT NULL,
	`user_name` VARCHAR(100) NOT NULL,
	`password` VARCHAR(100) NOT NULL,
	PRIMARY KEY (`user_name`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB;
</pre>
<p style="text-align: left;">A screenshot of the development environment is provided below. Make sure the mysql drivers, jstl libraries and tlds are all available. For making your life easy, we have included a hot deployable WAR file at the end of the workshop.</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" title="Simple Registration App Environment Folder structure" src="https://www.tech-freaks.com/wp-content/uploads/2013/02/registrationapp_env_setup.png" alt="Simple Registration App Environment Folder structure" width="316" height="371" border="0" /></p>
<hr class="system-pagebreak" title="Coding and Unit Testing" />
<p style="text-align: left;"><strong>Coding and Unit testing:</strong></p>
<p style="text-align: left;"><span style="line-height: 1.3em;">First, we would look at the ConnectionUtil. Below are the methods we would need for the ConnectionUtil. Note that we create this class as a static class (A class with static methods).Ã‚ </span></p>
<p style="text-align: left;">&#8211; <em>getConnection()</em><br />
<em>&#8211; closeConnection()</em><br />
<em>&#8211; executeQuery(String strQuery)</em></p>
<p style="text-align: left;">If you have read the article about simple login application, you would have already noticed thatt we just refactored the first two methods out of the LoginServlet. We prevent the code to be spread across multiple servlets this way. It is used to get a SQL Connection object and to close an open connection respectively.</p>
<p style="text-align: left;">In this example, we would use <em>java.sql.Statement</em> instead of <em>java.sql.PrepareStatement</em> which we used in LoginServlet, to spice things up. We need to pass the complete query to the Statement object to execute a query. The executeQuery can take an insert / update query and execute it. It would internally call getConnection() and closeConnection() to fetch and close a connection.</p>
<p style="text-align: left;">Below is the method executeQuery:</p>
<pre class="language-java"><code>public static void executeQuery(String strQuery) throws Exception {
		Connection conn = null;
		
		try {
			conn = getConnection();
			Statement stmt  = conn.createStatement();
			stmt.executeUpdate(strQuery);
			
		} catch (SQLException sqle) {
			System.out.println("SQLException: Unable to execute query : "+strQuery);
			throw sqle;
		} catch (Exception e) {
			System.out.println("Exception: Unable to execute query: "+strQuery);
			throw e;
		} finally {
			closeConnection(conn);
		}
	}</code></pre>
<pre class="brush:java" style="text-align: left;"></pre>
<p style="text-align: left;">We also moved the static variables like database name, db user name and db password from the servlet to the ConnectionUtil.</p>
<pre class="language-java"><code>        private static final String DBNAME = "tf_loginappdb";
	private static final String DB_USERNAME = "root";
	private static final String DB_PASSWORD = "admin*";</code></pre>
<pre style="text-align: left;"></pre>
<p style="text-align: left;">If your database has different dbname, username or password, you will need to update this and recompile you java file for the application to be able to connect to MySQL database.</p>
<p>Next, we would look at the code in the RegistrationServlet. It gets all the fields from the RegistrationForm in the request parameters. Below are the methods which we would add to this servlet.</p>
<p style="text-align: left;"><em>&#8211; doPost()</em><br />
<em>&#8211; validateData()</em><br />
<em>&#8211; setRequestAttributes()</em><br />
<em>&#8211; generateInsertQuery()</em></p>
<p style="text-align: left;">The doPost is the entry point to the servlet for html form POST. We have all the controller logic in here. The other methods are in a way, do not do the controller work. We use them for simple tasks which do not warranty creating other classes in our case. However, in a real life application, if the task is complex we might want to create new classes to delegate the task.</p>
<p style="text-align: left;">validateData() is used to implement the requirement that the userName and password cannot be empty. It validates and returns a boolean indicating success or failure of the validation.</p>
<p style="text-align: left;">generateInsertQuery() fetches the request parameters and generates the insert query which will be passed on to the executeQuery method of the ConnectionUtil. Below is the code for the method:</p>
<pre class="brush:java" style="text-align: left;"></pre>
<pre class="language-java"><code> private String generateInsertQuery(HttpServletRequest request) {
		String strUserName = request.getParameter("userName");
		String strPassword = request.getParameter("password");
		String strFirstName = request.getParameter("firstName");
		String strLastName = request.getParameter("lastName");
		String strEmail = request.getParameter("email");
		String strSecretQuestion = request.getParameter("secretQuestion");
		String strSecretAnswer = request.getParameter("secretAnswer");

		StringBuffer strQuery = new StringBuffer(INSERT_QUERY_START);
		strQuery.append(strFirstName);
		strQuery.append("', '");
		strQuery.append(strLastName);
		strQuery.append("', '");
		strQuery.append(strEmail);
		strQuery.append("', '");
		strQuery.append(strSecretQuestion);
		strQuery.append("', '");
		strQuery.append(strSecretAnswer);
		strQuery.append("', '");
		strQuery.append(strUserName);
		strQuery.append("', '");
		strQuery.append(strPassword);
		strQuery.append("')");
		
		System.out.println("Insert query : "+strQuery.toString());
		
		return strQuery.toString();

	}
 </code></pre>
<pre class="brush:java" style="text-align: left;">
setRequestAttributes() is used to implement the requirement about maintaining the data entered in the registration form in the even of an error. Do you remember banging your head against the keyboard after filling up a long registration form and clicking submit, only to find the form reloading with an error message and all the data you entered spending hours, boom! gone!<img decoding="async" title="Yell" src="media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-yell.gif" alt="Yell" border="0" /></pre>
<p style="text-align: left;">Instead of the classic get each parameter and set to attribute, we would just do a generic loop through. This would keep the code small. Imagine your registration form is 100 fields instead, the below code will not require any modification. Below is the code:</p>
<pre class="language-java"><code>	private void setRequestAttributes(HttpServletRequest request) {
		Enumeration  enumKeys =  request.getParameterNames();
		while(enumKeys.hasMoreElements()) {
			String key  = enumKeys.nextElement();
			request.setAttribute(key, request.getParameter(key))  ;
		}
	} </code></pre>
<pre class="brush:java" style="text-align: left;"></pre>
<p style="text-align: left;">The doPost() method is provided below. It has inline comment to explain key control logic. Once the insert in the database is successful, we set the userName is session and redirect to Home.jsp.</p>
<p style="text-align: left;">The error messages are managed by putting a request attribute on error situation and forwarding back to RegistrationForm. You will see the difference between the redirect and forward. You will see that the request attributes are available and also the URL of the servlet remains the same after the request is forwarded to the JSP. Also, note how we utilize the primary key duplicate error message and set the error message. We use the same pattern to set error message, set the request attributes and forward to registration page on all the error conditions.</p>
<pre class="language-java"><code>protected void doPost(HttpServletRequest request, HttpServletResponse 
			response) throws ServletException, IOException {
		
		String strUserMsg = null;
		HttpSession session = request.getSession();
		RequestDispatcher reqDisp =  request.getRequestDispatcher(REGISTRATION_PAGE);
		
		try {
			//Check if data is valid
			if(validateData(request)) {
				ConnectionUtil.executeQuery(generateInsertQuery(request));
				System.out.println("Insert into database successful");
				session.setAttribute("userName", request.getParameter("userName"));
				response.sendRedirect(getServletContext().getContextPath()+HOME_PAGE);
			} else {//If data is invalid
				strUserMsg = "User Name and Password cannot be empty";
				setRequestAttributes(request);
				request.setAttribute("userMsg", strUserMsg);
				reqDisp.forward(request, response);
			}
			
		} catch(SQLException sqle ) {
			System.out.println("Unable to register user: "+sqle.getMessage());
			//Check if we are getting duplicate key exception on userName
			if(sqle.getMessage().indexOf("Duplicate entry")!=-1) {
				System.out.println("User already exists");
				strUserMsg = "User name "+request.getParameter("userName")+" already " +
						"exists. Please try another user name.";
			} else { //If other SQLException than dup key exception
				strUserMsg = "Unable to register user "+request.getParameter("userName")+
				". Please try again later.";
			}
			setRequestAttributes(request);
			request.setAttribute("userMsg", strUserMsg);
			reqDisp.forward(request, response);

		} catch(Exception e) {//If it goes into Exception other than SQLException
			System.out.println("Unable to register user: "+e.getMessage());
			strUserMsg = "Unable to register user "+request.getParameter("userName")
			+". Please try again later.";
			setRequestAttributes(request);
			request.setAttribute("userMsg", strUserMsg);
			reqDisp.forward(request, response);

		}
		
		

	}</code></pre>
<pre class="brush:java" style="text-align: left;"></pre>
<p style="text-align: left;">Next, let us look at our RegistrationForm.jsp. We highlight small snippet of code here</p>
<pre class="language-markup"><code>&lt;p&gt;&lt;font color="#ff0000"&gt;&lt;c:out value="${userMsg}"/&gt;&lt;/font&gt;&lt;/p&gt;
&lt;form name="frmRegistration" method="post" action="&lt;c:out value="${pageContext.servletContext.contextPath}" /&gt;/servlet/RegistrationServlet"&gt;
&lt;table border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First Name&lt;/td&gt;
&lt;td&gt;&lt;input type="text" name="firstName" value ="&lt;c:out value="${firstName}"/&gt;" size="20"&gt;&lt;/td&gt;</code></pre>
<ul style="text-align: left;">
<li><span style="line-height: 1.3em;">JSTL is used display the userMsg which we set in the request attribute in our servlet.</span></li>
<li><span style="line-height: 1.3em;">JSTL is used to pick the contextPath from servletContext</span></li>
<li><span style="line-height: 1.3em;">JSTL is used to display user entered data in the event of an error</span></li>
</ul>
<p style="text-align: left;">We picked up the Home.jsp from the simple login application. You can get the complete WAR file to the simple registration application by clicking <a title="SimpleRegistrationApp" href="sourcecode/SimpleRegistrationApp/SimpleRegistrationApp.war" target="_blank" rel="noopener noreferrer">SimpleRegistrationApp.war</a>.</p>
<p style="text-align: left;">You just need to hot deploy SimpleRegistrationApp.war to webapps folder in the Tomcat program file and it would explode. Verify the application by accessing http://localhost:8080/SimpleRegistrationApp/RegistrationForm.jsp and run some tests to figure out how it works for you.</p>
<p style="text-align: left;">Feel free to leave a comment below, if you run into any issues. Enjoy!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-freaks.com/java/jsp-servlets/simple-registration-application.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Javascript with JSON</title>
		<link>https://www.tech-freaks.com/java/javascript/json-javascript.html</link>
					<comments>https://www.tech-freaks.com/java/javascript/json-javascript.html#respond</comments>
		
		<dc:creator><![CDATA[Tech Programmer]]></dc:creator>
		<pubDate>Sun, 20 Jan 2013 05:10:11 +0000</pubDate>
				<category><![CDATA[Javascript]]></category>
		<guid isPermaLink="false">http://localhost/tfcom_wp/2013/01/20/json-javascript/</guid>

					<description><![CDATA[This workshop is for you, if: You are looking for a data structure to store your data for easy javascript [&#8230;]]]></description>
										<content:encoded><![CDATA[		<div class="wpulike wpulike-default " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="77"
					data-ulike-nonce="2a5c878e38"
					data-ulike-type="post"
					data-ulike-template="wpulike-default"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_77"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p style="text-align: left;"><strong>This workshop is for you, if:</strong></p>
<ul style="text-align: left;">
<li>You are looking for a data structure to store your data for easy javascript access</li>
<li>You have seen JSON structure but do not know, how to access it using javascript</li>
</ul>
<p style="text-align: left;"><strong>This workshop is not for you, if:</strong></p>
<ul style="text-align: left;">
<li>You have no idea about client side scripting</li>
</ul>
<p style="text-align: left;">This workshop intends to provide hands on example on creating JSON structure and accessing the contents of the JSON using Javascript.</p>
<p style="text-align: left;"><strong>&#8216;JSON&#8217; the new kid in town</strong></p>
<p style="text-align: left;">JSON which stands for JavaScript Object Notation is the new buzz word and will definitely look good in your resume! But, how is JSON useful from a technology perspective.</p>
<ul style="text-align: left;">
<li>JSON can store data in the client side, where data security is not important.</li>
<li>JSON can be used for data exchange just like XML. But, why not XML itself? JSON comes handy when the exchanged data needs to be handled in the client side. JSON structure is easy to be manipulated in client side using javascript.</li>
</ul>
<p style="text-align: left;"><strong>Workshop Requirement</strong></p>
<p style="text-align: left;">Let us say, we need to maintain the summary of contents of this website. We want the data not to be maintained in database. We need to get information from a data structure using Javascript and of course, this data is not sensitive. The website contains, two sections (while writing this article), Java Programming and Stock Market. Each section contains categories and each category contains articles. Based on this data, we would like to see the number of pages in Java category etc.</p>
<p style="text-align: left;"><strong>Meeting JSON flesh and blood</strong></p>
<p style="text-align: left;">Enough talking about JSON! Let us actually see a JSON structure. The code snippet provided below shows a JSON structure assigned to a Javascript variable. When we use JSON for data exchange, we will write or receive JSON structure starting from braces without the javascript variable. To convert this into a javascript variable, we can use &#8216;eval&#8217; function, which is not recommended. There are parsers available in <a title="www.json.org" href="http://www.json.org/" target="_blank" rel="nofollow noopener noreferrer"><span style="text-decoration: underline;"><span style="color: #800080;">JSON.org</span></span></a> which converts the JSON structure to javascript variable.</p>
<pre class="language-javascript"><code>var varSiteData = {
  "sections" : [ //Array
     {//Each element in array, ie. Section is a structure not a simple attribute
      "name": "Java Programming", //this is a simple attribute
      "categories": [
      {
         "name":"Java Basics",
         "articles": [
         {
            "name" : "Java Hello World",
            "pages" : "1",
            "author" : "Tech Programmer"         
         },
         {
            "name" : "Java Hello World using Eclipse IDE",
            "pages" : "5",
            "author" : "Tech Programmer"         
         },
         ...
         ...
       ]
      },
      ...
      ...
     ]
    },
    ...
    ....
   ]
 }</code></pre>
<pre class="code-style" style="text-align: left;"></pre>
<p style="text-align: left;">Let us try to understand the syntax. JSON always start and end with curly braces. They contain attributes. The value of each attribute can be simple string, a structure (which internally is composed of many simple string attributes), array of simple string or array of structures. Here &#8220;section&#8221; is an attribute. How many sections we have in the site? Two, Java programming and Stock market. This calls for an array. Arrays are defined by square brackets. Now, each section contains categories. Also, each section needs a name to be stored. So, we have added an attribute by &#8220;name&#8221;. Attribute &#8220;name&#8221; is a simple string. Other attributes shown work in the same way. Click <a title="JSON in JS" href="sourcecode/JSON/v1/website_json.js" target="_blank" rel="nofollow noopener noreferrer">here</a> to download the complete JSON structure stored in JS file.</p>
<dl id="tf-message">
<dd class="message message fade">
<ul>
<li>An attribute name or key cannot start with numeric value. Although this is not a rule written anywhere, when the key or attribute name starts with or is a numeric value, the javascript which parse through the JSON does not understand the key. A simple workaround to resolve this issue is to append a constant string before the numeric value. Example: &#8220;str_25&#8221;</li>
</ul>
</dd>
</dl>
<p style="text-align: left;"> One more important thing is, if for an attribute, the value needs to be multiple attributes but not an array, then it is achieved using curly brackets only. A simple snippet which shows the attribute structure for Alphonsa mango:</p>
<pre class="language-javascript"><code>"alphonsa" : {
  "type": "mango",
  "taste": "sweet",
  "color": "yellow"
}</code></pre>
<p style="text-align: left;">Well, that&#8217;s that. We got started with JSON. But, let us try to have a quick look, why JSON is compared with XML. See the above JSON structure in an XML format.</p>
<pre class="language-markup"><code>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
&lt;sections&gt;
  &lt;section&gt;
     &lt;name&gt;Java Programming&lt;/name&gt;
     &lt;category&gt;
        &lt;name&gt;Java Basics&lt;/name&gt;
        &lt;article&gt;
           &lt;name&gt;Java Hello World&lt;/name&gt;
           &lt;pages&gt;1&lt;/pages&gt;
           &lt;author&gt;Tech Programmer&lt;/author&gt;
        &lt;/article&gt;
        &lt;article&gt;
           &lt;name&gt;Java Hello World using Eclipse IDE&lt;/name&gt;
           &lt;pages&gt;5&lt;/pages&gt;
           &lt;author&gt;Tech Programmer&lt;/author&gt;
        &lt;/article&gt;
       ...
       ...
     &lt;/category&gt;
  &lt;/section&gt;
..
&lt;/sections&gt;</code></pre>
<p style="text-align: left;"><strong>Validating JSON structure</strong></p>
<p style="text-align: left;">Just like we validate XML structures using Internet Explorer and other tools for well-formedness, there are certain JSON viewers available, which verify the JSON structure and provide details regarding any missing braces etc. <a title="JSON Viewer" href="http://www.codeplex.com/JsonViewer" target="_blank" rel="nofollow noopener noreferrer"><span style="text-decoration: underline;"><span style="color: #800080;">JSON Viewer</span></span></a> is one such hand helpful too.</p>
<p style="text-align: left;"><strong>Javascript and JSON</strong></p>
<p style="text-align: left;">Now, let us see how Javascript can access different elements within the JSON structure. We will try to calculate the total number of pages in &#8216;Stock Market&#8217; and &#8216;Java Programming&#8217; section. The HTML page includes the JSON data from a JS file. The javascript present in the HTML page iterates through the JSON structure to determine the result.</p>
<p style="text-align: left;">See the below javascript function, with comments explaining how the JSON structure is iterated through.</p>
<pre class="language-javascript"><code>function getSectionTotalPages(section) {

 //entry point into JSON variable..Accessing sections attribue, which is an array
 var arrSections = varSiteData.sections;
 var totalPages = 0;
 //loop through each of the sections
 for(var i=0;i&lt;arrSections.length;i++) {
  var currSection = arrSections[i];
  //we get the section for which we want to calculate the page total
  if(currSection.name==section) {
   //Now into category array from section
   var arrCategories = currSection.categories;
   
   //loop through the category array
   for(var j=0;j&lt;arrCategories.length;j++) {
    var currCategory = arrCategories[j];
    //For each category, get the article list (array)
    var arrArticles = currCategory.articles;
    //loop through each article
    for(var k=0;k&lt;arrArticles.length;k++) {
     var currArticle = arrArticles[k];
 
     //for each article, get the # of pages and add it to total
     totalPages = totalPages + parseInt(currArticle.pages);
    }
   }
   //This method works for one section, so break the loop, if the section is found
   break;
  }
 }
 return totalPages;
}</code></pre>
<pre class="brush:javascript" style="text-align: left;"><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; font-size: 1rem;">The complete HTML containing the javascripts is given below. On clicking the compare button, the compareSectionPages function is called. It internally,calls getSectionTotalPages function twice, for getting pages for </span><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; font-size: 1rem;">'</span><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; font-size: 1rem;">Java Programming</span><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; font-size: 1rem;">'</span><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; font-size: 1rem;"> section and </span><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; font-size: 1rem;">'</span><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; font-size: 1rem;">Market Analysis</span><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; font-size: 1rem;">'</span><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; font-size: 1rem;"> section.</span></pre>
<pre class="language-markup"><code>&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;JSON and Javascript example&lt;/title&gt;
  &lt;script type="text/javascript" src="website_json.js" &gt;&lt;/script&gt;
  &lt;script language="javascript" type="text/javascript"&gt;
  function getSectionTotalPages(section) {
 var arrSections = varSiteData.sections;
 var totalPages = 0;
 for(var i=0;i&lt;arrSections.length;i++) {
  var currSection = arrSections[i];
  if(currSection.name==section) {
   var arrCategories = currSection.categories;
  for(var j=0;j&lt;arrCategories.length;j++) {

    var currCategory = arrCategories[j];
    var arrArticles = currCategory.articles;
    for(var k=0;k&lt;arrArticles.length;k++) {
     var currArticle = arrArticles[k];
     totalPages = totalPages + parseInt(currArticle.pages);
    }
   }
   break;
  }
 }
 return totalPages;
}

  function compareSectionPages() {
   var totalJavaPages = getSectionTotalPages('Java Programming');
 var totalMarketPages = getSectionTotalPages('Market Analysis');
   var result = "&lt;table border='1'&gt;&lt;tr&gt;&lt;td&gt;Java Programming&lt;/td&gt;&lt;td&gt;Market Analysis&lt;/td&gt;

&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;"+totalJavaPages+"&lt;/td&gt;&lt;td&gt;"+totalMarketPages+"&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;";
   document.getElementById('result').innerHTML = result;
  }

  &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h2&gt;Welcome to JSON with javascript workshop!&lt;/h2&gt;
  &lt;p&gt;
  &lt;input type="button" name="button1" value="Compare Section pages" onclick="compareSectionPages();"&gt;

  &lt;p&gt;&lt;p&gt;
  Result: &lt;div id="result"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p style="text-align: left;"> And the result is 17 to 12. Java programming wins by 5 goals!</p>
<p style="text-align: left;">The author of the &#8216;Market analysis&#8217; section may feel bit hard done by.  Some articles missed out were missed out. &#8216;Technical Analysis&#8217; and &#8216;Market Summary&#8217; articles were not considered. We added every article inside the category, but these two articles are not maintained at category level. They are maintained in section level.</p>
<hr class="system-pagebreak" title="JSON flexibility" />
<p style="text-align: left;">Well, change is inevitable in the JSON structure! However, the flexibility of JSON will cover up for it. But, the change in data structure will cause a change to javascript code to calculate the total pages in section.</p>
<p style="text-align: left;">Let us get this thing fixed. For the JSON fix, a little thought will make it clear that adding articles inside section structure will be similar to articles maintained inside categories. The below code snippet shows the portion of the changed JSON:</p>
<pre class="code-style" style="text-align: left;"></pre>
<pre class="language-javascript"><code> ...
      {
      "name":"Market Analysis",
      "articles": [
       {
          "name": "Market Summary",
          "pages": "1",
          "author" : "Market Analyst"        
       },
       {
          "name": "Tech Analysis",
          "pages": "1",
          "author" : "Market Analyst"        
       }
      ] 
      ....
     .....</code></pre>
<p style="text-align: left;">The change in  getSectionTotalPages will be bit more challenging. Now, in the code we have to deal with one section, which has articles array and another which does not. Also, this method needs to be generic enough to handle any new sections added to the website in the future. Some of the section may have articles inside it and some may not. Many times, while using javascript we see the &#8216;undefined&#8217; variable. We will have to use this, to check if articles array is present directly within sections.</p>
<p>The below modified function getSectionTotalPages will do the trick. See the comments explaining the main changes and the <em>typeof</em> function used to good effect.</p>
<pre class="language-javascript"><code>function getSectionTotalPages(section) {
 var arrSections = varSiteData.sections;
 var totalPages = 0;
 for(var i=0;i&lt;arrSections.length;i++) {
  var currSection = arrSections[i];
  if(currSection.name==section) {
   //Check if articles inside section is undefined (does not exist)
   //If not undefined, then section as articles like Market Analysis section
   if(typeof(currSection.articles)!='undefined') {

    var arrSecArticles = currSection.articles;
    for(var j=0;j&lt;arrSecArticles.length;j++) {
     var currSecArticle = arrSecArticles[j];
     totalPages = totalPages + parseInt(currSecArticle.pages);

    }
   }
   var arrCategories = currSection.categories;

   for(var j=0;j&lt;arrCategories.length;j++) {
    var currCategory = arrCategories[j];
    var arrArticles = currCategory.articles;
    for(var k=0;k&lt;arrArticles.length;k++) {
     var currArticle = arrArticles[k];
     totalPages = totalPages + parseInt(currArticle.pages);
    }
   }
   break;
  }
 }
 return totalPages;
}</code></pre>
<p style="text-align: left;">Update the HTML code contents with the above updated function. Click <span style="text-decoration: underline;"><span style="color: #0066cc;"><a title="JSON structure" href="sourcecode/JSON/v2/website_json.js" target="_blank" rel="nofollow noopener noreferrer">here</a></span></span> to download the updated JSON code. Place the HTML and JS file in the same directory. Access the HTML page from browser and then click the &#8216;Compare Section pages&#8217; button to view the result table. &#8216;Java Programming&#8217; still wins by a margin of 3!</p>
<p style="text-align: left;">Welcome to the whole new world of client side scripting with JSON!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-freaks.com/java/javascript/json-javascript.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
