Showing posts with label J2EE. Show all posts
Showing posts with label J2EE. Show all posts

Sunday, 2 March 2014

Servlets Introduction

🚀 Master Java Web Development!

Building your foundational software engineering skills? Subscribe to Ram N Java for more clear, beginner-friendly programming guides!

🔔 Subscribe to Ram N Java

What is a Java Servlet?

A Java Servlet is a server-side Java program that runs inside a Web Container (such as Apache Tomcat) to handle incoming client requests and generate dynamic web responses.

Before Servlets became standard, web servers handled dynamic content primarily using CGI (Common Gateway Interface) scripts. Servlets replaced CGI by introducing high-performance, robust, and platform-independent request processing powered by the Java Virtual Machine.

Why Every Java Developer Needs to Know Servlets

Even if modern Java developers frequently build applications using higher-level frameworks like Spring MVC or Spring Boot, understanding Servlets remains essential:

  • The Backbone of Web Frameworks: Underneath Spring Boot and Spring MVC, the entire request lifecycle is handled by the DispatcherServlet, which is fundamentally a Java Servlet.
  • Mastering the Request-Response Cycle: Servlets teach you firsthand how HTTP protocols, request parsing, headers, cookies, and session management actually function.
  • Debugging Confidence: When debugging filters, interceptors, authentication flows, or connection issues in enterprise web applications, servlet-level knowledge makes troubleshooting straightforward.

Key Advantages of Java Servlets

  1. High Performance (Multi-Threading): Unlike traditional CGI scripts that spawned an entirely new operating system process for each incoming request, a servlet container creates a lightweight Java thread per request.
  2. Platform Independence: Write once, run on any operating system supporting a compliant Java Servlet container.
  3. Security & Robustness: Benefit directly from Java's built-in memory management, exception handling, and JVM type safety.
  4. Extensibility: Integrate seamlessly with enterprise Java features such as JDBC, JTA, and connection pooling.

How a Servlet Request Lifecycle Works

When a browser triggers a URL mapped to your servlet:

  • The container checks if the servlet is already loaded; if not, it instantiates the class and calls init().
  • For every client hit, a separate thread invokes the service() method.
  • The servlet constructs dynamic content (HTML, JSON, XML) and writes it into the HttpServletResponse output stream.
  • When shutting down, the container triggers destroy() to release active resources.

Recommended Related Tutorials

Continue your web development journey with these hand-picked tutorials from Ram N Java:


Click here to watch in Youtube : https://www.youtube.com/watch?v=BrvAYxN8jjM

Click the below Image to Enlarge
Servlets Introduction

Servlets Introduction

Servlets Introduction

See also:

  • Servlets Tutorial
  • All Design Patterns Links
  • Sunday, 29 September 2013

    Service Locator Design Pattern - KeyPoints

    🚀 Level Up Your Enterprise Java Skills!

    Subscribe to Ram N Java for clean software design patterns, enterprise Java architecture, and clear coding tutorials!

    🔔 Subscribe to Ram N Java

    What Is the Service Locator Design Pattern?

    In distributed and enterprise Java applications, clients frequently need to find and consume various business services (such as EJBs, JMS queues, or data sources). When clients look up these services directly using complex APIs like JNDI, it leads to tight coupling, redundant network calls, and poor performance. The Service Locator Design Pattern centralizes distributed service lookup and caching to solve these challenges cleanly.

    Key Takeaways & Core Concepts

    • Centralized Lookup Mechanism: All JNDI or remote service resolution logic is consolidated into a single locator component, keeping client code free of lookup complexities.
    • High-Performance Caching: The Service Locator caches previously resolved service objects. When another client requests the same service, the locator returns the cached reference immediately without costly network trips.
    • Encapsulation of Vendor Complexity: Hides initial context creation, connection factory initialization, and low-level naming exceptions behind a clean, simple API.
    • Loose Coupling: Clients depend only on the abstract service interface and the Service Locator, shielding them from backend vendor shifts or configuration changes.

    Core Architecture Participants

    1. Client: The object that needs to invoke operations on a business service.
    2. Service Locator: The centralized entry point that looks up services and manages the internal cache.
    3. InitialContext: The underlying directory lookup environment (such as JNDI) that resolves the remote object reference.
    4. Service (Interface): The contract that specifies the business operations available to the client.
    5. Cache: An in-memory data store within the locator that holds active service references for reuse.

    Major Architectural Benefits

    • Significant Performance Boost: Eliminates duplicate network overhead by serving repeat service requests directly from the cache.
    • Cleaner Client Code: UI and client components do not need boilerplate try-catch blocks for JNDI naming exceptions.
    • Simplified Maintenance: Any change in service discovery logic or JNDI namespaces is updated in only one place.

    Recommended Next Videos

    Continue your deep dive into service discovery and enterprise patterns with these tutorials from our channel:


    Click here to watch in Youtube : https://www.youtube.com/watch?v=fxfAJS9O74M

    Click the below Image to Enlarge

    Sunday, 8 September 2013

    Service Locator Design Pattern - Implementation

    🚀 Level Up Your Java Architecture Skills!

    Subscribe to Ram N Java for clean code walkthroughs, design pattern implementations, and step-by-step programming guides!

    🔔 Subscribe to Ram N Java

    Practical Implementation of Service Locator

    In distributed Java enterprise applications, resolving business services via JNDI or remote directory lookups can be costly and repetitive. The Service Locator Design Pattern solves this by centralizing service lookups and employing an in-memory cache. Once a service is resolved, subsequent requests retrieve it instantly from the cache without triggering another expensive network call.

    Building Blocks of the Implementation

    • Service (Interface): Defines the common business contract (such as getName() and execute()) implemented by concrete services.
    • Concrete Services: Concrete classes (e.g., Service1, Service2) that implement the business methods.
    • InitialContext: Simulates or encapsulates the JNDI lookup mechanism to instantiate requested services by name.
    • Cache: Stores already-instantiated service objects so repeat calls avoid directory lookups.
    • ServiceLocator: The central entry point containing a static method (e.g., getService(String jndiName)) that coordinates between the Cache and the InitialContext.
    • Client: The application component that queries the ServiceLocator to execute business logic cleanly.

    Step-by-Step Execution Flow

    1. The Client requests a service by providing its JNDI name to the ServiceLocator.
    2. The ServiceLocator checks the Cache to see if an instance of that service already exists.
    3. Cache Hit: If found in the cache, the locator immediately returns the cached instance to the client.
    4. Cache Miss: If not found, the locator invokes the InitialContext to look up and instantiate the service.
    5. The new service instance is saved into the Cache for future lookups and then returned to the client.

    Implementation Best Practices

    • Thread-Safe Caching: Ensure your cache data structure (e.g., ConcurrentHashMap or synchronized collections) handles concurrent lookups safely in multi-threaded environments.
    • Centralize Exception Handling: Catch and handle naming and context initialization exceptions inside the locator to avoid propagating low-level errors to clients.
    • Program to Interfaces: Always return the abstract Service interface rather than concrete classes to keep client code decoupled and flexible.

    Recommended Next Videos

    Broaden your understanding of enterprise tier architecture with these related tutorials from our channel:


    Click here to watch in Youtube : https://www.youtube.com/watch?v=4MaBWg44fbs

    Click the below Image to Enlarge





















    Service.java

    public interface Service
    {
    public void execute();
    public String getName();
    }


    JMSService.java


    public class JMSService implements Service
    {

    @Override
    public void execute()
    {
    System.out.println("Executing JMSService");

    }
    @Override
    public String getName()
    {
    return "JMSService";
    }

    }

    EJBService.java


    public class EJBService implements Service
    {

    @Override
    public void execute()
    {
    System.out.println("Executing EJBService");
    }

    @Override
    public String getName()
    {
    return "EJBService";
    }

    }

    InitialContext.java


    public class InitialContext
    {
    public Object lookup( String jndiName )
    {
    if( jndiName.equalsIgnoreCase("EJBService") )
    {
    // JNDI lookup code will come in real time implementation
    System.out.println("Looking up and creating a new EJBService object");
    return new EJBService();
    }
    else if( jndiName.equalsIgnoreCase("JMSService") )
    {
       // JNDI lookup code will come in real time implementation
    System.out.println("Looking up and creating a new JMSService object");
    return new JMSService();
    }
    return null;
    }
    }

    Cache.java


    import java.util.ArrayList;
    import java.util.List;

    public class Cache
    {
    private List<Service> services;

    public Cache()
    {
    services = new ArrayList<Service>();
    }

    public Service getService( String serviceName )
    {
    for( Service service : services )
    {
    if( service.getName().equalsIgnoreCase(serviceName) )
    {
    System.out.println("Return cached  " + serviceName + " object");
    return service;
    }
    }
    return null;
    }

    public void addService( Service newService )
    {
    boolean exists = false;
    for( Service service : services )
    {
    if( service.getName().equalsIgnoreCase(newService.getName()) )
    {
    exists = true;
    }
    }
    if( !exists )
    {
    services.add(newService);
    }
    }
    }

    ServiceLocator.java


    public class ServiceLocator
    {
    private static Cache cache;

    static
    {
    cache = new Cache();
    }

    public static Service getService( String jndiName )
    {
    // First check the service object available in cache
    Service service = cache.getService(jndiName);

    if( service != null )
    {
    return service;
    }

    /*
    * If service object not available in cache do the lookup using
    * JNDI initial context and get the service object and add it to
    * the cache for future use
    */
    InitialContext context = new InitialContext();
    Service service1 = (Service) context.lookup(jndiName);
    cache.addService(service1);
    return service1;
    }
    }


    Client.java


    public class Client
    {

    public static void main( String[] args )
    {
    Service service = ServiceLocator.getService("EJBService");
    service.execute();
    System.out.println();
    service = ServiceLocator.getService("JMSService");
    service.execute();
    System.out.println();
    service = ServiceLocator.getService("EJBService");
    service.execute();
    System.out.println();
    service = ServiceLocator.getService("JMSService");
    service.execute();

    }

    }

    Output

    Looking up and creating a new EJBService object
    Executing EJBService

    Looking up and creating a new JMSService object
    Executing JMSService

    Return cached  EJBService object
    Executing EJBService

    Return cached  JMSService object
    Executing JMSService

    Service Locator Design Pattern - Class and Sequence Diagram

    🚀 Master Object-Oriented Architecture!

    Subscribe to Ram N Java for clean diagrams, enterprise design patterns, and clear step-by-step programming guides!

    🔔 Subscribe to Ram N Java

    Understanding the Service Locator Architecture

    In distributed and enterprise Java systems, resolving business services repeatedly through JNDI directory lookups can introduce significant network latency and tight coupling. The Service Locator Design Pattern solves this challenge by centralizing lookup logic and maintaining an in-memory cache of service instances. Understanding its static structure through a Class Diagram and runtime interactions through a Sequence Diagram makes mastering this pattern simple and practical.

    Class Diagram: Participants and Structural Roles

    The class diagram represents the core structural components and how they relate to one another:

    • Client: The application object or controller that requires access to a business service.
    • ServiceLocator: The central facade holding a static lookup method (e.g., getService(String jndiName)) and maintaining references to both the InitialContext and the Cache.
    • InitialContext: The object that performs the low-level lookup or instantiation of the requested service via naming directories.
    • Cache: A dedicated repository (such as a map or list) used by the locator to store and retrieve previously resolved service references.
    • Service (Interface): The common interface that defines the operations provided by concrete business services.
    • Concrete Services: Implementations (such as Service1 and Service2) that fulfill the business requests.

    Sequence Diagram: Execution Flow Step-by-Step

    The sequence diagram illustrates how messages travel dynamically when a client requests a service:

    1. Request Initiation: The Client calls ServiceLocator.getService("serviceName").
    2. Cache Inspection: The ServiceLocator checks the Cache to see if the requested service object already exists in memory.
    3. Case A (Cache Hit): If found, the Cache returns the service instance directly to the locator, which passes it immediately back to the client. No directory lookup is performed.
    4. Case B (Cache Miss): If not found, the locator invokes the InitialContext to resolve and instantiate the concrete service.
    5. Cache Update: The newly created service instance is registered into the Cache for future lookups.
    6. Execution: The locator hands the service instance to the client, which then invokes the required business methods (e.g., execute()).

    Key Architectural Benefits

    • Significant Performance Optimization: Caching resolved objects prevents repetitive, expensive remote network lookups.
    • Loose Coupling: The client depends strictly on the Service interface, completely isolated from vendor-specific directory naming mechanisms.
    • Simplified Client Code: Eliminates boilerplate lookup try-catch blocks across multiple presentation and business components.

    Recommended Next Videos

    Expand your knowledge of enterprise UML diagrams and design patterns with these tutorials from our channel:


    Click here to watch in Youtube : https://www.youtube.com/watch?v=a-JeUQwjUGY

    Click the below Image to Enlarge

    Business Delegate Design Pattern - Introduction

    🚀 Master Java Enterprise Architecture!

    Subscribe to Ram N Java for beginner-friendly design pattern tutorials, clean enterprise architectures, and step-by-step guides!

    🔔 Subscribe to Ram N Java

    Introduction to the Business Delegate Pattern

    In multi-tier enterprise applications, having presentation components (such as UI controllers, Servlets, or JSPs) communicate directly with backend business services creates tight coupling and complex dependencies. The Business Delegate Design Pattern solves this challenge by introducing an intermediary layer that decouples the presentation tier from the business tier.

    Why Do We Need a Business Delegate?

    Connecting client code directly to distributed enterprise services leads to several architectural problems:

    • Tight Coupling: Any modification in remote service APIs or transport protocols requires extensive rewrites across presentation code.
    • Repeated Lookups: Performing remote lookups repeatedly across various UI components degrades system performance.
    • Complex Error Handling: Front-end controllers become cluttered with low-level network and distributed system exceptions.

    A Business Delegate acts as a protective shield, handling service lookups, caching references, and converting system-level exceptions into simple application errors.

    Core Architecture Participants

    1. Client: The presentation tier component that requests business services via the delegate.
    2. Business Delegate: The entry point that provides a clean, unified interface to the client and coordinates with backend services.
    3. Lookup Service (Service Locator): The component that locates and instantiates the target business service.
    4. Business Service: The enterprise component that performs the actual business operations.

    Key Architectural Benefits

    • Cleaner Presentation Code: Front-end developers only need to interact with simple Java objects instead of remote service endpoints.
    • Optimized Performance: Client-side caching of business service stubs reduces redundant network requests.
    • Seamless Maintenance: Backend business services can be refactored, migrated, or replaced with zero impact on UI classes.

    Recommended Next Videos

    Deepen your enterprise software design skills with these related tutorials from our channel:


    Click here to watch in Youtube : https://www.youtube.com/watch?v=BT6I6PWEuiM

    Click the below Image to Enlarge
    Business Delegate Design Pattern - Introduction

    Tutorials