JAX-RS සමඟ Java RESTful Web Services - API හැදීමේ සම්පූර්ණ මාර්ගෝපදේශය

JAX-RS සමඟ Java RESTful Web Services - API හැදීමේ සම්පූර්ණ මාර්ගෝපදේශය

ආයුබෝවන් යාලුවනේ! RESTful Web Services ගැන කතා කරමු

ඉතින් කොහොමද යාලුවනේ! අද අපි කතා කරන්න යන්නේ Software Engineering ලෝකයේ ගොඩක් වැදගත් මාතෘකාවක් ගැන. ඒ තමයි Java භාවිතයෙන් RESTful Web Services හදන හැටි. විශේෂයෙන්ම අපි JAX-RS කියන Java API එක ගැනයි බලන්නේ. මේක හරියට, ඔයාගේ Application එකට වෙනත් Application එකක් සමඟ කතාබස් කරන්න පුළුවන් දොරටුවක් හදනවා වගේ වැඩක්. අද කාලේ හැම තැනම වගේ APIs භාවිත වෙන නිසා, මේක දැනගෙන ඉන්න එක ඔයාගේ Skills වලට ගොඩක් වටිනවා.

අපි මේ ලිපිය පුරාවටම JAX-RS කියන්නේ මොකක්ද, ඒක කොහොමද වැඩ කරන්නේ, ඒ වගේම @Path, @GET, @POST වගේ ප්‍රධාන annotations ටික භාවිත කරලා practical විදියට RESTful Endpoints ටිකක් කොහොමද හදාගන්නේ කියලා පියවරෙන් පියවර බලමු. මේක Java වලින් Backend Development වලට අත ගහන අයට වගේම දැනටමත් මේ ක්ෂේත්‍රයේ ඉන්න අයටත් හොඳ refresher එකක් වෙයි කියලා මම හිතනවා.

හරි එහෙනම්, අපි පටන් ගමු!

REST සහ JAX-RS හැඳින්වීම: මේවා මොනවද?

REST (Representational State Transfer) කියන්නේ මොකක්ද?

සරලවම කිව්වොත්, REST කියන්නේ Web Services හදන්න භාවිත කරන architecture style එකක්. මේක Web එක කොහොමද වැඩ කරන්නේ කියන එකේ මූලික සිද්ධාන්ත මත පදනම් වෙලා තියෙනවා. RESTful APIs කියන්නේ, HTTP methods (GET, POST, PUT, DELETE) භාවිත කරලා, resources (දත්ත) manipulate කරන API ටිකක්. නිකමට හිතන්න, ඔයාගේ phone එකේ Facebook app එක Facebook servers එක්ක කතා කරන්නේ මේ වගේ APIs හරහා තමයි. ඒ වගේම, web browsers වෙබ් අඩවි වලට request කරලා දත්ත ලබාගන්නෙත් මේ වගේ ක්‍රමවේදයක් භාවිත කරලයි.

REST වල ප්‍රධානම දේවල් ටිකක් තමයි:

  • Resources: API එකක් හරහා manipulate කරන්න පුළුවන් ඕනෑම දත්ත කට්ටලයක් (උදා: user, product, order).
  • URIs (Uniform Resource Identifiers): සෑම resource එකකටම unique address එකක් තියෙනවා (උදා: /users, /products/123).
  • HTTP Methods: Resources මත operations කරන්න භාවිත කරන ක්‍රම (GET - දත්ත ලබාගැනීමට, POST - දත්ත එකතු කිරීමට, PUT - දත්ත update කිරීමට, DELETE - දත්ත මකා දැමීමට).
  • Stateless: සෑම request එකක්ම වෙන වෙනම හඳුනා ගන්න පුළුවන්. Server එක client ගේ previous request එකක් ගැන මතක තියාගන්නේ නැහැ.
  • Media Types: දත්ත හුවමාරු කරගන්න භාවිත කරන format එක (උදා: JSON, XML). අද කාලේ JSON තමයි ගොඩක් වෙලාවට භාවිත වෙන්නේ.

JAX-RS (Java API for RESTful Web Services) කියන්නේ මොකක්ද?

JAX-RS කියන්නේ Java වලින් RESTful Web Services හදන්න පුළුවන් specification එකක්. සරලවම කිව්වොත්, මේක Standard API එකක්. මේ API එක implement කරන Frameworks ගොඩක් තියෙනවා, ඒ අතරින් Jersey, RESTEasy, Apache CXF වගේ ඒවා ජනප්‍රියයි. අපි මේ ලිපියේදී JAX-RS reference implementation එකක් වන Jersey භාවිත කරනවා. JAX-RS මඟින් අපිව HTTP request එකක් Java code එකක් දක්වා map කරන්න ඕන කරන annotations සහ classes ටිකක් ලබා දෙනවා.

JAX-RS ව්‍යාපෘතියක් ආරම්භ කිරීම (Setting Up a JAX-RS Project)

JAX-RS project එකක් හදන්න කලින් ඔයාගේ පරිගණකයේ Java Development Kit (JDK) එකක් (Java 8 හෝ ඊට වැඩි Version එකක්) සහ Maven (Dependency Management සඳහා) install කරලා තියෙන්න ඕනේ. අපි මේ සඳහා Maven භාවිත කරනවා.

1. Maven Project එකක් හදාගමු

මුලින්ම ඔයාගේ IDE එකේ (IntelliJ IDEA, Eclipse වගේ එකක) අලුත් Maven Project එකක් හදාගන්න. Project Type එක maven-archetype-webapp විදියට තෝරගන්න. එහෙම නැත්නම් command line එකේ පහත විධානය ක්‍රියාත්මක කරන්න:

mvn archetype:generate -DgroupId=com.mycompany.restapi -DartifactId=my-rest-service -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

2. pom.xml එකට Dependencies එකතු කිරීම

දැන් අපි Jersey Framework එකට අවශ්‍ය Dependencies ටික pom.xml file එකට එකතු කරමු. jersey-server සහ jersey-container-servlet-core කියන දෙක තමයි ප්‍රධාන වශයෙන්ම අවශ්‍ය වෙන්නේ. අපි Maven එකේ latest stable version එකක් භාවිත කරමු.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany.restapi</groupId>
    <artifactId>my-rest-service</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>my-rest-service Maven Webapp</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <jersey.version>2.35</jersey.version> <!-- Latest stable version -->
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>my-rest-service</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.1</version>
            </plugin>
        </plugins>
    </build>
</project>

මෙහිදී jersey-media-json-jackson කියන එක එකතු කරේ JSON data handle කරන්න පහසු වෙන්න. ඒක තමයි ගොඩක් වෙලාවට භාවිත වෙන්නේ.

3. web.xml File එක Configure කිරීම

Jersey servlet එක deploy කරන්න src/main/webapp/WEB-INF/web.xml file එක configure කරන්න ඕනේ. මේ file එකේදී අපි Jersey Application class එක define කරනවා, ඒ වගේම Servlets map කරනවා.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">

    <display-name>my-rest-service</display-name>

    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.mycompany.restapi.resources</param-value> <!-- Your package where resources are -->
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

</web-app>

මෙහිදී <param-value>com.mycompany.restapi.resources</param-value> කියන තැනට ඔයාගේ RESTful resources තියෙන Java package එකේ නම දෙන්න ඕනේ. ඒ වගේම <url-pattern>/api/*</url-pattern> කියන්නේ, ඔයාගේ API එකේ හැම Endpoint එකක්ම /api/ කියන base path එකෙන් පටන් ගන්නවා කියන එකයි. උදාහරණයක් විදියට, /api/books, /api/users වගේ.

@Path Annotation එක භාවිතය: Your Resource's Address

@Path Annotation එක තමයි JAX-RS වලදී resource එකක හෝ resource method එකක URI එක define කරන්න භාවිත වෙන්නේ. මේක Class level එකේදී භාවිත කරද්දී, ඒ Class එකේ තියෙන හැම Method එකකටම පොදු base path එකක් define කරනවා. Method level එකේදී භාවිත කරද්දී, ඒ Method එකටම විශේෂිත path එකක් define කරනවා.

@Path Class එකක් සඳහා

අපි හිතමු අපිට Books manage කරන්න API එකක් හදන්න ඕනේ කියලා. මේ සඳහා අපි BookResource කියලා Class එකක් හදාගමු. මේ Class එකේදී අපි @Path("/books") කියලා දානවා.

package com.mycompany.restapi.resources;

import javax.ws.rs.Path;

@Path("/books")
public class BookResource {
    // Methods for handling book operations will go here
}

දැන් මේ BookResource Class එක ඇතුළේ අපි හදන හැම method එකකම base URI එක වෙන්නේ /api/books (web.xml එකේ දැම්ම /api prefix එකත් එක්ක).

@Path Method එකක් සඳහා

Class level එකේ @Path එකට අමතරව, ඔයාට පුළුවන් Method level එකේ @Path එකක් දාලා, ඒ Method එකටම විශේෂිත URI segment එකක් define කරන්න. උදාහරණයක් විදියට, එක specific book එකක් ලබාගන්න.

package com.mycompany.restapi.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/books")
public class BookResource {

    // Dummy Book class for demonstration
    public static class Book {
        private String id;
        private String title;
        private String author;

        public Book() {}

        public Book(String id, String title, String author) {
            this.id = id;
            this.title = title;
            this.author = author;
        }

        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
        public String getAuthor() { return author; }
        public void setAuthor(String author) { this.author = author; }
    }

    // Get all books
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getAllBooks() {
        return "[{"id":"1", "title":"The Great Gatsby", "author":"F. Scott Fitzgerald"}, {"id":"2", "title":"1984", "author":"George Orwell"}]";
    }

    // Get a specific book by ID
    @GET
    @Path("/{bookId}") <!-- Method-level path segment -->
    @Produces(MediaType.APPLICATION_JSON)
    public String getBookById(@PathParam("bookId") String bookId) {
        // In a real application, you'd fetch from a database
        if ("1".equals(bookId)) {
            return "{"id":"1", "title":"The Great Gatsby", "author":"F. Scott Fitzgerald"}";
        } else if ("2".equals(bookId)) {
            return "{"id":"2", "title":"1984", "author":"George Orwell"}";
        } else {
            return "{}"; // Or return a 404 Not Found response
        }
    }
}

මෙතනදී @Path("/{bookId}") කියන එකෙන් කියන්නේ, URI එකේ /books/ කියන එකට පස්සේ එන segment එක bookId කියන variable එකට අරගන්නවා කියන එකයි. @PathParam("bookId") එකෙන් ඒ bookId එක Java Method එකේ parameter එකකට bind කරනවා. ඉතින්, /api/books/1 කියලා request එකක් ආවොත්, bookId එකට "1" කියන value එක ලැබෙනවා.

@GET සමඟ දත්ත ලබාගැනීම (Fetching Data with @GET)

@GET Annotation එක JAX-RS වලදී භාවිත වෙන්නේ HTTP GET request එකක් handle කරන්න. RESTful APIs වලදී GET request එකක් භාවිත වෙන්නේ server එකෙන් දත්ත ලබාගැනීමටයි. මේවා idempotent operations. ඒ කියන්නේ, එකම request එක කීප වතාවක් යැව්වත්, server එකේ තත්ත්වයේ වෙනසක් වෙන්නේ නැහැ.

සියලුම දත්ත ලබාගැනීම

උඩ code එකේ getAllBooks() Method එක බලන්න. ඒක @GET විතරක් භාවිත කරනවා. ඒ කියන්නේ /api/books කියන URI එකට GET request එකක් ආවොත්, මේ method එක execute වෙනවා.

@Produces(MediaType.APPLICATION_JSON) කියන එකෙන් කියන්නේ, මේ method එකෙන් return කරන data එක JSON format එකෙන් client ට යවන්න ඕනේ කියන එකයි. JAX-RS වලදී MediaType class එකෙන් common media types define කරලා තියෙනවා (APPLICATION_JSON, APPLICATION_XML, TEXT_PLAIN වගේ).

Test කරන්න: ඔයාට Postman වගේ tool එකක් භාවිත කරලා http://localhost:8080/my-rest-service/api/books (ඔයාගේ server port එක සහ project name එකට අනුව වෙනස් වෙන්න පුළුවන්) කියන URI එකට GET request එකක් යවන්න පුළුවන්.

Path Parameters සමඟ විශේෂිත දත්ත ලබාගැනීම

getBookById(@PathParam("bookId") String bookId) Method එක තමයි මේකට උදාහරණය. අපි කලින් කතා කරපු @Path("/{bookId}") එක සමඟ මේක වැඩ කරනවා. ඒකෙන් පුළුවන් URI එකේ කොටසක් variable එකක් විදියට අරගෙන, ඒක Method parameter එකකට bind කරන්න. මේවා සාමාන්‍යයෙන් resource එකක ID එකක් වගේ unique identifier එකක් specify කරන්න භාවිත කරනවා.

Test කරන්න: http://localhost:8080/my-rest-service/api/books/1 වගේ URI එකකට GET request එකක් යවලා බලන්න.

Query Parameters සමඟ දත්ත පෙරීම (Filtering Data)

සමහර වෙලාවට අපිට දත්ත ටිකක් filter කරලා ගන්න අවශ්‍ය වෙනවා. ඒකට අපි Query Parameters භාවිත කරනවා. මේවා URI එකේ ? ලකුණෙන් පස්සේ key=value යුගල විදියට එනවා. JAX-RS වලදී මේවා bind කරන්න @QueryParam Annotation එක භාවිත කරනවා.

package com.mycompany.restapi.resources;

// ... imports ...
import javax.ws.rs.QueryParam;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Path("/books")
public class BookResource {

    // Dummy Book class (as defined before)
    public static class Book {
        private String id;
        private String title;
        private String author;

        public Book() {}
        public Book(String id, String title, String author) { this.id = id; this.title = title; this.author = author; }
        // Getters and Setters...
        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
        public String getAuthor() { return author; }
        public void setAuthor(String author) { this.author = author; }
    }

    // Dummy Data Store
    private static List<Book> books = new ArrayList<>(
        Arrays.asList(
            new Book("1", "The Great Gatsby", "F. Scott Fitzgerald"),
            new Book("2", "1984", "George Orwell"),
            new Book("3", "To Kill a Mockingbird", "Harper Lee"),
            new Book("4", "Animal Farm", "George Orwell")
        )
    );

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Book> getBooks(@QueryParam("author") String author, @QueryParam("title") String title) {
        // If both are null, return all books
        if (author == null && title == null) {
            return books;
        }

        // Filter logic (simplified for demonstration)
        return books.stream()
                .filter(book -> {
                    boolean matches = true;
                    if (author != null) {
                        matches = matches && book.getAuthor().toLowerCase().contains(author.toLowerCase());
                    }
                    if (title != null) {
                        matches = matches && book.getTitle().toLowerCase().contains(title.toLowerCase());
                    }
                    return matches;
                })
                .collect(Collectors.toList());
    }

    @GET
    @Path("/{bookId}")
    @Produces(MediaType.APPLICATION_JSON)
    public Book getBookById(@PathParam("bookId") String bookId) {
        return books.stream()
                .filter(book -> book.getId().equals(bookId))
                .findFirst()
                .orElse(null); // In a real app, return 404 or specific error
    }
}

මෙහිදී getBooks method එකට @QueryParam("author") String author සහ @QueryParam("title") String title එකතු කරලා තියෙනවා. ඉතින්, client කෙනෙක් /api/books?author=George%20Orwell කියලා request කළොත්, ඒ author ගේ පොත් විතරක් return වෙනවා. /api/books?title=farm වගේ request එකකට title එකේ 'farm' තියෙන පොත් return වෙනවා.

List<Book> return කරන්න පුළුවන් වෙන්න අපි Dummy Book Class එකත් හදලා, jersey-media-json-jackson dependency එක හරහා ඒක JSON format එකට Convert වෙන්න සලස්වලා තියෙනවා.

@POST සමඟ දත්ත එකතු කිරීම (Adding Data with @POST)

@POST Annotation එක භාවිත වෙන්නේ HTTP POST request එකක් handle කරන්න. RESTful APIs වලදී POST request එකක් ප්‍රධාන වශයෙන්ම server එකට අලුත් දත්ත (resource එකක්) එකතු කරන්න භාවිත වෙනවා. මේවා idempotent නොවේ. ඒ කියන්නේ, එකම POST request එක කීප වතාවක් යැව්වොත්, server එකේ දත්ත කිහිප වතාවක් save වෙන්න පුළුවන්.

අලුත් පොතක් එකතු කිරීම

අපි BookResource එකට අලුත් පොතක් එකතු කරන්න Method එකක් ලියමු.

package com.mycompany.restapi.resources;

// ... existing imports ...
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.core.Response; // For returning HTTP status codes
import java.util.concurrent.atomic.AtomicLong;

@Path("/books")
public class BookResource {

    // Dummy Book class (as defined before)
    public static class Book {
        private String id;
        private String title;
        private String author;

        public Book() {}
        public Book(String id, String title, String author) { this.id = id; this.title = title; this.author = author; }
        // Getters and Setters...
        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
        public String getAuthor() { return author; }
        public void setAuthor(String author) { this.author = author; }
    }

    // Dummy Data Store and ID Generator
    private static List<Book> books = new ArrayList<>(
        Arrays.asList(
            new Book("1", "The Great Gatsby", "F. Scott Fitzgerald"),
            new Book("2", "1984", "George Orwell"),
            new Book("3", "To Kill a Mockingbird", "Harper Lee"),
            new Book("4", "Animal Farm", "George Orwell")
        )
    );
    private static AtomicLong idCounter = new AtomicLong(4); // Start after existing IDs

    // ... existing GET methods ...

    @POST
    @Consumes(MediaType.APPLICATION_JSON) <!-- Expects JSON input -->
    @Produces(MediaType.APPLICATION_JSON) <!-- Returns JSON output -->
    public Response addBook(Book newBook) {
        if (newBook.getTitle() == null || newBook.getAuthor() == null) {
            return Response.status(Response.Status.BAD_REQUEST).entity("{\"error\": \"Title and Author are required.\"}").build();
        }
        String newId = String.valueOf(idCounter.incrementAndGet());
        newBook.setId(newId);
        books.add(newBook);
        System.out.println("Added book: " + newBook.getTitle());
        return Response.status(Response.Status.CREATED).entity(newBook).build();
    }
}

මෙතනදී අලුත් දේවල් කීපයක් තියෙනවා:

  • @Consumes(MediaType.APPLICATION_JSON): මේ Annotation එකෙන් කියන්නේ, මේ method එකට එන HTTP request එකේ body එක JSON format එකෙන් තියෙන්න ඕනේ කියන එකයි. JAX-RS (සහ Jackson library එක) 자동으로 JSON data එක Book object එකකට bind කරනවා.
  • public Response addBook(Book newBook): මෙහිදී Method parameter එකක් විදියට Book object එකක් අරගන්නවා. request body එකේ JSON payload එක මේ Book object එකට convert වෙනවා.
  • Response.status(Response.Status.CREATED).entity(newBook).build(): සාර්ථකව resource එකක් create කළාම, HTTP 201 Created status code එකක් return කරන එක හොඳ practice එකක්. Response class එක JAX-RS වලදී HTTP response එක control කරන්න භාවිත කරනවා. entity() method එකෙන් response body එකට යවන්න ඕනේ object එක specify කරනවා.
  • Error Handling: අපි පොඩි validation එකක් දාලා, Title හෝ Author නැත්නම් 400 Bad Request එකක් return කරනවා.

Test කරන්න: Postman වගේ tool එකක් භාවිත කරලා http://localhost:8080/my-rest-service/api/books URI එකට POST request එකක් යවන්න. Request Body එකේ raw JSON විදියට මෙහෙම දෙන්න:

{
    "title": "The Alchemist",
    "author": "Paulo Coelho"
}

Request එක යැව්වම ඔයාට 201 Created Status එකත් එක්ක අලුතින් add වුණ Book object එක JSON විදියට ලැබෙන්න ඕනේ.

අවසන් වශයෙන්: JAX-RS සමඟ RESTful API ලෝකයට පිවිසෙමු

ඉතින් යාලුවනේ, මේ ලිපියෙන් අපි JAX-RS කියන බලගතු Java API එක භාවිත කරලා RESTful Web Services හදන හැටි ගැන මූලික අවබෝධයක් ලබා ගත්තා. අපි @Path, @GET, @POST වගේ ප්‍රධාන annotations කොහොමද භාවිත කරන්නේ, ඒ වගේම Path Parameters, Query Parameters සහ Request Body එකට Data Bind කරන්නේ කොහොමද කියලා Practical විදියටම බැලුවා. මේවා තමයි ඕනෑම RESTful API එකක තියෙන මූලිකම ගොඩනැගිලි කොටස්.

RESTful APIs කියන්නේ අද කාලේ Software Development වලට නැතිවම බැරි දෙයක්. මේක හොඳට තේරුම් අරගෙන, තවදුරටත් practice කරන එක ඔයාගේ Development ගමනට ගොඩක් වැදගත් වෙයි. මතක තියාගන්න, මෙතනින් නවතින්න එපා. JAX-RS වල තව ගොඩක් දේවල් තියෙනවා: @PUT (Update), @DELETE (Delete), @FormParam, @HeaderParam, Error Handling, Exception Mappers, Security වගේ දේවල් ගැනත් ඉගෙන ගන්න බලන්න.

මේ ලිපිය ඔයාට ප්‍රයෝජනවත් වෙන්න ඇති කියලා හිතනවා. ඔයා මේක implement කරලා බැලුවද? මොනවා හරි ගැටලුවක් ආවද? නැත්නම් මේ ගැන තවත් දැනගන්න ඕන දේවල් තියෙනවා නම්, පහළින් Comment එකක් දාන්න. අපි ඒ ගැනත් කතා කරමු!

සුභ දවසක්! Happy Coding!