Tuesday, March 13, 2018

Java Websocket Example With Simple Server and Client

In usual websites, how the communication between the client(Browser) and the server happen is first the client(browser) sends a request to the server and the server responses to the client. Apart from this usual behavior, there can be situations where a server needs to send data to a client at an arbitrary time. A chat server is such an example.

The process of creation of a WebSocket connection between a a server and a client is as below.
First the client sends an HTTP request to the server with "Connection: Upgrade" and "Upgrade: websocket" headers. Once the server sees above headers it knows that the client wants to make a WebSocket connection.
Then the server sends a response to the client by including above two header parameters.
Websocket communication is done using TCP/IP protocol. So then the current HTTP connection is upgraded to a TCP/IP connection.

In below example, I will show you how to write a simple websocket client and a server. In order to keep this example clearer I purposely avoided introducing best practices and patterns to the code.

1.Server
Create a new maven project. Set the artifact name as WebsocketServer1 and packaging as war. Open the pom.xml and add below configs.
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
</dependencies>

Now we are going to create the class which acts as the server endpoint. Create a new class and name it as MyServerEndpoint. The content of the class will be as below.

import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/chat")
public class MyServerEndpoint {

  public MyServerEndpoint() {
      System.out.println("MyServerEndpoint created......");
  }

  @OnOpen
  public void onOpen(Session session) {
      System.out.printf("Connection opened....");
      try {
          session.getBasicRemote().sendText("Your connection accepted...");
      } catch (IOException ex) {
          ex.printStackTrace();
      }
  }
  
  @OnClose
  public void onClose(Session session) {
  System.out.printf("Connection closed....");
  }
  
  @OnError
  public void onError(Throwable e) {
  System.out.printf("Error occurred....");
  e.printStackTrace();
  }

  @OnMessage
  public void onMessage(String message, Session session) {
      System.out.printf("Message from client: " + message);
      try {
          session.getBasicRemote().sendText(String.format("Hi client, we got your message '" + message + "'"));
      } catch (IOException ex) {
          ex.printStackTrace();
      }
  }
}

Now you can run this web application in tomcat server. Then this endpoint will be deployed and will be listening on below endpoint.
ws://localhost:8080/WebsocketServer1/chat

2.Client
Now I am going to create a websocket client which can communicate with the above server.
Create a new maven project. Set the artifact name as WebsocketClient1 and the packaging as jar.
Add below dependencies to your pom.xml.
Note that javax.websocket-api contains the interfaces for websocket API.  Tyrus is an implementation of above API. Tomcat-websocket and jetty-websocket are another such implementations.

<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly</artifactId>
<version>1.1</version>
</dependency>

Create a new java class as below. This is your websocket client.

import java.net.URI;
import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;

@ClientEndpoint
public class MyClient {
    Session userSession = null;
    public static void main(String[] args) {
new MyClient().execute();
    }

    public void execute() {
try {
         URI endpointURI = (new URI("ws://localhost:8080/WebsocketServer1/chat"));
    WebSocketContainer container = ContainerProvider.getWebSocketContainer();
    Session session = container.connectToServer(this, endpointURI);

    sendMessage("Hello Server!");
    session.close();
} catch (Exception ex) {
    ex.printStackTrace();
}
    }

    @OnOpen
    public void onOpen(Session userSession) {
        this.userSession = userSession;
        System.out.println("Websocket connection opened.");
    }

    @OnClose
    public void onClose(Session userSession, CloseReason reason) {
        this.userSession = null;
        System.out.println("Websocket connection closed.");
    }

    @OnMessage
    public void onMessage(String message) {
        System.out.println("From server: " + message);
    }
    
    public void sendMessage(String message) {
        this.userSession.getAsyncRemote().sendText(message);
    }
}

Now we are ready to test our server and client. First run the server project on tomcat. Then run the client class. You will see below output in server console.
MyServerEndpoint created......
Connection opened....
Message from client: Hello Server!
Connection closed....

And you will see below output in clients console.
Websocket connection opened.
From server: Your connection accepted...
From server: Hi client, we got your message 'Hello Server!'
Websocket connection closed.

Below are the annotations used.
  @ServerEndpoint - Defines this as a server endpoint which is bound to the path given within brackets
  @OnOpen - This method gets executed when a connection between the client and the server is created
  @OnClose - This method gets executed when a connection is closed
  @OnError - This will be called if an unhandled excetion thrown in other annotated methods.
  @OnMessage This method gets executed when a message is received from other party
  @ClientEndpoint - Defines this as a websocket client. In order to the other annotation to work this annotation should be there.

Security:
DO not use unsecured websocket connections(ws://) in pages loaded in HTTPS. Instead, use secured (wss://) connections.

Friday, January 12, 2018

Generating a QR code using QRGen-javase API

QRGen javase is a simple QRCode generation API which makes QR Code generation easy. In this example, I will show you how to generate a QR Code and save it as an image in two minutes.

Create a new maven project. Add below maven dependancy in to your pom.xml.
<dependency>
    <groupId>net.glxn.qrgen</groupId>
    <artifactId>javase</artifactId>
    <version>2.0</version>
</dependency>

I want to create the barcode so that when someone scanned the code he gets the URL to my blog http://tech-lead.blogspot.com. Below is the java class that I am using to generate this QR code.

import net.glxn.qrgen.core.image.ImageType;
import net.glxn.qrgen.javase.QRCode;
import java.io.*;

public class CreateQrCode {
    public static void main(String[] args) {
        String url = "http://tech-lead.blogspot.com";
        String outputFile = "E:/qr.png";
        ByteArrayOutputStream bytes = QRCode.from(url).withSize(200, 200).to(ImageType.PNG).stream();

        try {
            OutputStream out = new FileOutputStream(outputFile);
            bytes.writeTo(out);
            out.flush();
            out.close();
            System.out.println("File created at " + outputFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Run the above main method and you will see the file is generated in the given location. See below image.


Thursday, November 2, 2017

JMS with ActiveMQ

JMS(or Java Message Service) API which is a part of java EE platform, provides a way to do communications between computers in a network by sending and receiving objects called messages. JMS API can be used to assure loose coupling, reliability, and asynchronousness of messaging.

JMS Architecture
Members of a JMS communication mainly consists of below components. Producers and Consumers are commonly called as clients.
  1. JMS Provider
    JMS Provider is the messaging system that implements the JMS API.
    Apache ActiveMQ, RabbitMQ, HornetQ and OpenJMS are some example JMS providers.
  2. Producer
  3. Sender of the message
  4. Consumer
  5. Receiver of the message

Involvement of these three members is shown in below diagram.



ActiveMQ as a JMS Provider

As I have mentioned before ActiveMQ is a JMS provider which implements the JMS API.

Below three classes show how to implement the above architecture using an ActiveMQ as an embedded broker.

Broker
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;

import javax.jms.Connection;
import javax.jms.JMSException;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.TransportConnector;

public class AMQService {
  public static final String BROKER_URI = "tcp://localhost:61616";
  private static ActiveMQConnectionFactory connectionFactory;
  private static Connection connection;
  static BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));

  public static void main(String[] args) {
    try {
      startBroker();
      startListener();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  private static void startBroker() {
    BrokerService broker = new BrokerService();
    TransportConnector connector = new TransportConnector();
    try {
      connector.setUri(new URI(BROKER_URI));
      broker.addConnector(connector);
      broker.start();
      System.out.println("Message broker started at " + BROKER_URI);
    } catch (URISyntaxException e) {
      e.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  private static void startListener() {
    connectionFactory = new ActiveMQConnectionFactory(BROKER_URI);
    try {
      connection = connectionFactory.createConnection();
      connection.start();
      System.out.println("Listener started....");
    } catch (JMSException e) {
      e.printStackTrace();
    }
  }
}


Producer
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Producer {

    private Connection connection;
    private Session session;
    private MessageProducer messageProducer;

    public void create(String destinationName) throws JMSException {
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
                AMQService.BROKER_URI);
        connection = connectionFactory.createConnection();
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue(destinationName);
        messageProducer = session.createProducer(destination);
    }

    public void close() throws JMSException {
        connection.close();
    }

    public void sendMessage(String message) throws JMSException {
        TextMessage textMessage = session.createTextMessage(message);
        messageProducer.send(textMessage);
        System.out.println("Producer sent: " + message);
    }
}

Consumer
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Consumer {

    private Connection connection;
    private Session session;
    private MessageConsumer messageConsumer;

    public void create(String destinationName) throws JMSException {

        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
                AMQService.BROKER_URI);
        connection = connectionFactory.createConnection();
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue(destinationName);
        messageConsumer = session.createConsumer(destination);
        connection.start();
    }

    public void close() throws JMSException {
        connection.close();
    }

    public String getMessage(int timeout) throws JMSException {
    String text = "";
        Message message = messageConsumer.receive(timeout);

        if (message != null) {
            TextMessage textMessage = (TextMessage) message;
            text = textMessage.getText();
            System.out.println("Consumer received: " + text);
        } else {
        text = "";
            System.out.println(text);
        }
        return text;
    }
}

You can use below class to test above consumer producer communication.
import javax.jms.JMSException;

public class Test {
private static Producer producer;
private static Consumer consumer;
private static String queueName = "queue1";
public static void main(String[] args) throws JMSException {
producer = new Producer();
producer.create(queueName);

consumer = new Consumer();
consumer.create(queueName);

try {
String message = "Hello my consumers....";
producer.sendMessage(message);

String receivedMessage = consumer.getMessage(1000);
String status = message.equals(receivedMessage) ? "Success..." : "Fail...";
System.out.println(status);
} catch (JMSException e) {
System.out.println("JMS Exception occurred");
}
producer.close();
consumer.close();
}
}

Friday, April 28, 2017

Creating a SOAP web service with Apache CXF and Spring

In this example, I will show you how to use Apache CXF together with Spring to create a simple SOAP web service which returns hard-coded user information.

In Eclipse create a new Maven project as below.
Go to File -> New -> Maven Project
Check the check box "Create a simple project(skip archetype selection)".
Click "Next".
Set below parameters.
Group Id : com.example
Artifact Id : CxfSoapExample
Packaging : war

Click "Finish".

You will see in project explorer that a project named "CxfSoapExample" has been created.
Open the pom.xml file.
You may see an error message in pom.XML file as below because you have no web.XML file created yet.
"web.xml is missing and is set to true"

This message will vanish as soon as you created the web.xml file. However, if this message is annoying you can right click on "Deployment Descriptor" node and click "Generate deployment descriptor stub" to create the web.xml file.

Ok, Now let's go back to the pom.xml file. In this tutorial. I am using CXF 3.1.4 and java 1.7. So add those properties and CXF dependencies into the pom.xml file.
My final pom.xml file looks like below.

<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>CxfSoapExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<properties>
<cxf.version>3.1.4</cxf.version>
<spring.version>4.3.0.RELEASE</spring.version>
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${spring.version}</version>
</dependency>
</dependencies>
</project>

Now right click on the project and select "Maven -> Update Project". In the popup window select the "CxfSoapExample" project and click "OK".

Now we are going to create below three java components.
1. UserService.java  - This is an interface in which we define the web service methods
    package example.cxf.service;

    import javax.jws.WebMethod;
    import example.cxf.data.User;

    public interface UserService {
@WebMethod
public User getUser(String requestedBy);
    }

2. UserServiceImpl.java - This is the implementation of UserService interface and will act as the actual service class.
    package example.cxf.service;

    import example.cxf.data.User;

    public class UserServiceImpl implements UserService {

@Override
public User getUser(String requestedBy) {
User user = new User();
user.setFirstName("John");
user.setLastName("Williams");
user.setAge(50);
user.setRequestedBy(requestedBy);
return user;
}
    }

3. User.java - This is just a java class which has variables and methods to store and access user information.

    package example.cxf.data;

    public class User {
private String firstName;
private String lastName;
private String requestedBy;
private int age;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getRequestedBy() {
return requestedBy;
}
public void setRequestedBy(String requestedBy) {
this.requestedBy = requestedBy;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
    }

Now in order to expose our service lets register it in beans.XML file.
Create a file in webapp/WEB-INF folder and name it as beans.xml.
Open the newly created file and add below content.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">

<jaxws:endpoint
       id="userService"
       implementor="example.cxf.service.UserServiceImpl"
       address="/userService" />

</beans>

Create the web.xml file in webapp/WEB-INF folder(If you haven't created yet) and add below content.
<?xml version="1.0" encoding="UTF-8"?>
<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_2_5.xsd" version="2.5">
  <display-name>CxfSoap2</display-name>
  <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
  <context-param>
<param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/beans.xml</param-value>
</context-param>

<servlet>
       <servlet-name>CXF-SERVLET</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>CXF-SERVLET</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

Now run the project in tomcat server.
You should be able to see the WSDL file generated for this service by visiting below link.

http://localhost:8080/CxfSoapExample/userService?wsdl

Below is a sample request and response retrieved from SOAP-UI for above service.


Friday, March 31, 2017

SNMP Introduction

SNMP or Simple Network Management Protocol is a standard way of transferring information of network devices like servers, computers, routers, printers, hubs etc. Today it has become very popular and most of the hardware vendors support this protocol. SNMPv3 is the latest version of SNMP protocol.

How SNMP Works

Below are the main components of SNMP management system
1. SNMP Manager
This is the software which collects information from dofferent components in the network. Usually this is installed on a computer where network administrators have easy access. SNMP Manager polls each devices in the network regularly for information. According to your interest you can purchase or use a free SNMP Manager.

Some of the things that SNMP Manager does are

  • Collects information on bandwidth usage.
  • Alerts on low disk space
  • Monitors disk space usage of servers
  • Monitors CPU usage of servers
  • Monitors Memory usage of servers
  • Alerts on thresholds of disk space, memory usage and CPU usage
  • Sets parameters in agents such as passwords and configurations.


2. SNMP Agent
This is a piece of software which is installed in network devices by the hardware manufacturer. If monitoring of the device is required you need to enable and configure the agent. SNMP Agents run on the devices on the network separately and responsible for collecting information and deliver to the SNMP Manager when polled. In some special situations such as in an error, the agent can initiate and send messages to the SNMP Manager even when it is not polled.

3. MIB(Management Information Base)
This is a database which is used by the manager and agents to exchange information.


SNMP uses UDP(User Datagram Protocol - used to send short messages between a client and a server) as the transport protocol.

Below are the default ports used.
UDP 161 - Manager does polling of agents via this port.
UDP 162 - Messages initiated by agents are sent to the manager via this port.

Monday, May 4, 2015

Spring RESTful web service simple example

In this quick and simple example you will learn how to write a RESTful web service with Spring in five minutes.
First create a new maven project. Below are my configurations.
Group Id: com.example
Artifact Id: SpringRestExample
Packaging: war

Add required dependencies to pom.xml. My pom.xml is now looks like this.
<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>prageeth.example</groupId>
  <artifactId>SpringRestExample</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <dependencies>
 <dependency>
  <scope>provided</scope>
  <groupId>javax.servlet</groupId>
  <artifactId>servlet-api</artifactId>
  <version>2.5</version>

 </dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.7.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.0.7.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.0.7.RELEASE</version>
</dependency>
  </dependencies>
</project>

Create web.xml file in main/webapp/WEB-INF folder and add entry for DispatcherServlet.
My web.xml is as below.
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee   
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemalocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <servlet>
<servlet-name>mySpringRest</servlet-name>
<servlet-class> 
           org.springframework.web.servlet.DispatcherServlet      
        </servlet-class>
<load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
<servlet-name>mySpringRest</servlet-name>
<url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

You can see I have defined the DispatcherServlet as mySpringRest in web.xml file.
So I have to create the file mySpringRest-servlet.xml in WEB-INF folder.

Now create the class RestExample in package com.example. This is the class in which we are going to write our RESTful services. I add one service method in to this class.

package com.example;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class RestExample {
  
  @RequestMapping(value="/hello", method = RequestMethod.GET)
  public String sayHello() {
    return "Hello!";
  }
}

Since I am using Spring annotations and my annotated classes are in com.example package, in my mySpringRest-servlet.xml file I say spirng to scan that package for annotated classes.

This is my final mySpringRest-servlet.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<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:jee="http://www.springframework.org/schema/jee" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

<context:component-scan base-package="com.example" />
<mvc:annotation-driven />

</beans>

Now run the project and test the url http://localhost:8080/SpringRestExample/user/hello
You will receive the message "hello".

You can write your service method to accept request parameters as below.
package com.example;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class RestExample {

  @RequestMapping(value = "/hello", method = RequestMethod.GET)
  public String sayHello(@RequestParam(required=false, defaultValue="") String name) {
    return "Hello " + name + "!";
  }
}
Call the service like this to see the result.
http://localhost:8080/SpringRestExample/user/hello?name=john

You can write your service method to access path variables(path parameters) as below.
package com.example;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class RestExample {
  
  @RequestMapping("/{regNumber}/{name}")
  public String sayHello(@PathVariable Integer regNumber, @PathVariable String name) {
    return "Hello " + name + ".Your registration number is " + regNumber;
  }
}

Call the service as below to see the output.
http://localhost:8080/SpringRestExample/user/123/john