{"id":46788,"date":"2024-01-26T00:00:00","date_gmt":"2024-01-26T08:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/"},"modified":"2025-11-13T12:56:51","modified_gmt":"2025-11-13T20:56:51","slug":"developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide","status":"publish","type":"post","link":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/","title":{"rendered":"Developing a Web-Based Survey Platform with Java Spring Boot: A Beginner\u2019s Guide"},"content":{"rendered":"<h2>What is a survey platform?<\/h2>\n<p>A survey is a research method used to collect data from a group of people. It is a tool that can be used to gather information about opinions, behaviors, and other characteristics of a population. Surveys can be conducted in various ways, such as through interviews, questionnaires, or online forms.<\/p>\n<p>Web-based survey platforms are becoming increasingly popular due to their many benefits. Here are some of the advantages of using web-based survey platforms:<\/p>\n<ul>\n<li>Faster: Web-based surveys can be completed more quickly than traditional methods because participants can respond at their own pace and from anywhere with an internet connection.<\/li>\n<li>More Accurate: The margin of error is significantly reduced with online surveys because participants enter their responses directly into a web survey. Since respondents record their own answers, there is no opportunity for an interviewer to misinterpret a response.<\/li>\n<li>Visually Engaging: Web-based surveys can include multimedia elements such as images and videos to make them more engaging and interactive.<\/li>\n<\/ul>\n<p>Web-based survey platforms offer a variety of features and functional requirements that can help you create effective surveys. Here are some of the most common features available in web-based survey tools:<\/p>\n<ul>\n<li>Question Types: Web-based survey platforms offer a variety of question types, such as multiple-choice, open-ended, rating scales, and more.<\/li>\n<li>Skip Logic: Skip logic allows you to customize the flow of your survey based on the respondent\u00e2\u0080\u0099s answers. It enables you to skip irrelevant questions and show only those relevant to the respondent.<\/li>\n<li>Real-time Analytics: Web-based survey platforms provide real-time analytics that allows you to track responses as they come in and analyze data in real-time.<\/li>\n<li>Mobile Compatibility: Web-based surveys can be optimized for mobile devices, making it easy for respondents to complete surveys on their smartphones or tablets.<\/li>\n<li>Integration with Other Tools: Web-based survey platforms can integrate with other tools such as email marketing software, CRM systems, etc.<\/li>\n<\/ul>\n<h2>What We&#8217;re Building<\/h2>\n<p>In this tutorial, we&#8217;ll be creating a web-based survey platform that leverages the power of Spring Boot and GridDB. For now, we will start with implementing open-ended questions, and the respondent can submit multiple responses. Finally, there will be a report showing the answers and the percentage of the answers per question.<\/p>\n<h3>Requirements<\/h3>\n<p>Based on the previous overview, we will have the following functional requirements:<\/p>\n<ol>\n<li>Display a list of surveys, responses, and answers<\/li>\n<li>Record answers<\/li>\n<li>Visualize answers in table and chart<\/li>\n<\/ol>\n<p>The out of scope: * User management (register, login, etc) * Survey management (create, edit, delete)<\/p>\n<blockquote>\n<p>In this tutorial we will seed our application with survey data from CSV files.<\/p>\n<\/blockquote>\n<h3>Where should we store the data?<\/h3>\n<p>The choice between SQL and NoSQL databases depends on specific requirements. However, here are some reasons why NoSQL databases are preferred over SQL databases for this system:<\/p>\n<ol>\n<li>Horizontal scalability: NoSQL databases typically provide easy horizontal scalability.<\/li>\n<li>Query Structure: In this case, there is no need for complex relational operations such as table joins.<\/li>\n<li>NoSQL databases are typically built with a distributed and decentralized architecture, enabling easy scaling by adding more nodes to the cluster.<\/li>\n<\/ol>\n<h3>Class diagram for online survey<\/h3>\n<p>Next, let&#8217;s tackle database design and high-level architecture. The class diagram for the survey platform is shown below.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/survey-erd.png\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/survey-erd.png\" alt=\"\" width=\"719\" height=\"661\" class=\"aligncenter size-full wp-image-29922\" srcset=\"\/wp-content\/uploads\/2024\/01\/survey-erd.png 719w, \/wp-content\/uploads\/2024\/01\/survey-erd-300x276.png 300w, \/wp-content\/uploads\/2024\/01\/survey-erd-600x552.png 600w\" sizes=\"(max-width: 719px) 100vw, 719px\" \/><\/a><\/p>\n<h3>Database design for online survey<\/h3>\n<p>From the above class diagram, we will create a database schema with the following attributes:<\/p>\n<ul>\n<li>\n<p>Survey<\/p>\n<p>This is the starting point for our system. This entity contains core information about each survey generated in the system. It has the following attributes:<\/p>\n<ul>\n<li><code>String id<\/code>: System generated unique identifier. It is the primary key.<\/li>\n<li><code>String title<\/code>: The overview of the survey<\/li>\n<li><code>String description<\/code>: The description for the purpose of the survey<\/li>\n<li><code>boolean isActive<\/code>: A boolean value that indicates whether the survey is still valid<\/li>\n<li><code>Date createdAt<\/code>: System-generated timestamp of survey creation<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Question<\/p>\n<p>This entity contains the questions available for a survey. It has the following attributes:<\/p>\n<ul>\n<li><code>String id<\/code>: System generated unique identifier. It is the primary key.<\/li>\n<li><code>String surveyId<\/code>: The ID to identify the parent survey<\/li>\n<li><code>String questionText<\/code>: The text of the question<\/li>\n<li><code>Integer position<\/code>: The order of the question among the questions in the survey<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>SurveyResponse<\/p>\n<p>This entity contains information about the response and the moment of start and finish responding to a survey. It has the following attributes:<\/p>\n<ul>\n<li><code>String id<\/code>: System generated unique identifier. It is the primary key.<\/li>\n<li><code>String surveyId<\/code>: The ID to identify the parent survey<\/li>\n<li><code>Date startedAt<\/code>: The date and time when the respondent starts responding to the survey<\/li>\n<li><code>Date completedAt<\/code>: The date and time when the respondent finishes responding to the survey.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Answer<\/p>\n<p>This entity contains the respondent&#8217;s answer for each question in the survey. It has the following attributes:<\/p>\n<ul>\n<li><code>String id<\/code>: System generated unique identifier. It is the primary key.<\/li>\n<li><code>String surveyResponseId<\/code>: The ID to identify the parent survey&#8217;s response<\/li>\n<li><code>String answer<\/code>: The date and time when the respondent starts responding to the survey<\/li>\n<li><code>Date createdAt<\/code>: The date and time when the respondent finishes responding to the survey.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>How to Set up the Project<\/h2>\n<h3>What you can do with Spring Boot<\/h3>\n<p>Spring boot offers a fast way to build applications. Spring Boot does not generate code to make edits to your files. Instead, when you start your application, Spring Boot dynamically wires up beans and settings and applies them to your application context. With Spring Boot, we can focus more on the business features and less on the infrastructure.<\/p>\n<h3>What you need to install<\/h3>\n<ul>\n<li><a href=\"https:\/\/jdk.java.net\/21\/\">Java 17 or later<\/a>, <a href=\"https:\/\/maven.apache.org\/download.cgi\">Maven 3.5+<\/a>, and your favorite text editor (<a href=\"https:\/\/spring.io\/guides\/gs\/intellij-idea\/\">Intellij IDEA<\/a>, or <a href=\"https:\/\/spring.io\/guides\/gs\/guides-with-vscode\/\">VSCode<\/a>)<\/li>\n<\/ul>\n<h3>Create a Spring Boot Project<\/h3>\n<p>Navigate to <a href=\"https:\/\/start.spring.io\/\">start.spring.io<\/a>. This service pulls in all the dependencies you need for an application and does most of the setup. Follow the screenshot below then click generate, it will generate the Spring Boot project and download it as a zip.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/springboot-initializr.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/springboot-initializr.png\" alt=\"\" width=\"1000\" height=\"647\" class=\"aligncenter size-full wp-image-29920\" srcset=\"\/wp-content\/uploads\/2024\/01\/springboot-initializr.png 1000w, \/wp-content\/uploads\/2024\/01\/springboot-initializr-300x194.png 300w, \/wp-content\/uploads\/2024\/01\/springboot-initializr-768x497.png 768w, \/wp-content\/uploads\/2024\/01\/springboot-initializr-600x388.png 600w\" sizes=\"(max-width: 1000px) 100vw, 1000px\" \/><\/a><\/p>\n<p>Now unzip this project and import it into any IDE.<br \/>\nNext, we need to add additional library needed in this project as follows:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">&lt;dependencies&gt;\n&lt;!-- Include log4j2 --&gt;\n&lt;dependency&gt;\n  &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n  &lt;artifactId&gt;spring-boot-starter-log4j2&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n  \n&lt;dependency&gt;\n  &lt;groupId&gt;com.github.griddb&lt;\/groupId&gt;\n  &lt;artifactId&gt;gridstore&lt;\/artifactId&gt;\n  &lt;version&gt;5.1.0&lt;\/version&gt;\n&lt;\/dependency&gt;\n\n&lt;dependency&gt;\n  &lt;groupId&gt;com.github.f4b6a3&lt;\/groupId&gt;\n  &lt;artifactId&gt;tsid-creator&lt;\/artifactId&gt;\n  &lt;version&gt;5.2.5&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n  &lt;groupId&gt;de.siegmar&lt;\/groupId&gt;\n  &lt;artifactId&gt;fastcsv&lt;\/artifactId&gt;\n  &lt;version&gt;2.2.2&lt;\/version&gt;\n&lt;\/dependency&gt;\n\n&lt;\/dependencies&gt;<\/code><\/pre>\n<\/div>\n<h3>Coding<\/h3>\n<h4>Data access with GridDB<\/h4>\n<p>First, we create Java POJO classes that represent the underlying table or container in GridDB. We annotate a class with Lombok @Data, which automatically generates getters for all fields, a useful toString method, and hashCode and equals implementations that check all non-transient fields. Also generate setters for all non-final fields, as well as a constructor.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">@Data\npublic class Survey {\n    @RowKey String id;\n    String title;\n    String description;\n    boolean isActive;\n    Date createdAt;\n}\n\n@Data\npublic class SurveyResponse {\n  @RowKey String id;\n  String respondentId;\n  String surveyId;\n  Date startedAt;\n  Date completedAt;\n}\n\n@Data\npublic class Answer {\n  @RowKey String id;\n  String surveyResponseId;\n  String questionId;\n  Date createdAt;\n  String answer;\n}\n\n@Data\npublic class Question {\n  @RowKey String id;\n  String surveyId;\n  String questionText;\n  Integer position;\n}\n\n@Data\npublic class Respondent {\n  @RowKey String id;\n}<\/code><\/pre>\n<\/div>\n<p>Next, we create the <code>GridDBConfig<\/code> class as a central configuration for database operation. The class will do the following: * Read environment variables for connecting to the GridDB database * Create a GridStore class for managing database connection to the GridDB instance * Create GridDB Collection&#8217;s container (Table) to manage a set of rows. The container is a rough equivalent of the table in a relational database. * On creating\/updating the Collection we specify the name and object corresponding to the column layout of the collection. Also for each collection, we add an index for a column that is frequently searched and used in the condition of the WHERE section of TQL.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">@Configuration\npublic class GridDBConfig {\n\n  @Value(\"${GRIDDB_NOTIFICATION_MEMBER}\")\n  private String notificationMember;\n\n  @Value(\"${GRIDDB_CLUSTER_NAME}\")\n  private String clusterName;\n\n  @Value(\"${GRIDDB_USER}\")\n  private String user;\n\n  @Value(\"${GRIDDB_PASSWORD}\")\n  private String password;\n\n  @Bean\n  public GridStore gridStore() throws GSException {\n    \/\/ Acquiring a GridStore instance\n    Properties properties = new Properties();\n    properties.setProperty(\"notificationMember\", notificationMember);\n    properties.setProperty(\"clusterName\", clusterName);\n    properties.setProperty(\"user\", user);\n    properties.setProperty(\"password\", password);\n    GridStore store = GridStoreFactory.getInstance().getGridStore(properties);\n    return store;\n  }\n\n  @Bean\n  public Collection&lt;String, Survey> surveyCollection(GridStore gridStore) throws GSException {\n    Collection&lt;String, Survey> collection = gridStore.putCollection(\"surveys\", Survey.class);\n    return collection;\n  }\n\n  @Bean\n  public Collection&lt;String, Respondent> respondentCollection(GridStore gridStore)\n      throws GSException {\n    Collection&lt;String, Respondent> collection =\n        gridStore.putCollection(\"respondents\", Respondent.class);\n    return collection;\n  }\n\n  @Bean\n  public Collection&lt;String, SurveyResponse> surveyResponseCollection(GridStore gridStore)\n      throws GSException {\n    Collection&lt;String, SurveyResponse> collection =\n        gridStore.putCollection(\"surveyResponses\", SurveyResponse.class);\n    collection.createIndex(\"surveyId\");\n    collection.createIndex(\"respondentId\");\n    return collection;\n  }\n\n  @Bean\n  public Collection&lt;String, Question> questionCollection(GridStore gridStore) throws GSException {\n    Collection&lt;String, Question> collection = gridStore.putCollection(\"questions\", Question.class);\n    collection.createIndex(\"surveyId\");\n    return collection;\n  }\n\n  @Bean\n  public Collection&lt;String, Answer> answerCollection(GridStore gridStore) throws GSException {\n    Collection&lt;String, Answer> urlCollection = gridStore.putCollection(\"answers\", Answer.class);\n    urlCollection.createIndex(\"surveyResponseId\");\n    return urlCollection;\n  }\n}<\/code><\/pre>\n<\/div>\n<h4>Service class<\/h4>\n<p>Next, we create a service class with @Service annotation for handling business logic and convert the Entity class into DTO. For example, the <code>SurveyService.java<\/code> is responsible for finding, and creating survey data in GridDB.<\/p>\n<ul>\n<li><code>create<\/code>: Creating a new survey row. This method receives data from a web request (<code>SurveyWebController<\/code>) and then assigns the value to a new Survey entity. For saving the entity into the GridDB database, we call the <code>put<\/code> method from the <code>surveyCollection<\/code> bean created before.<\/li>\n<\/ul>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">public String create(SurveyCreateRequest request) {\n    Survey survey = new Survey();\n    survey.setId(KeyGenerator.next(\"survey\"));\n    survey.setActive(request.isActive());\n    survey.setTitle(request.getTitle());\n    survey.setDescription(request.getDescription());\n    survey.setCreatedAt(new Date());\n    try {\n      log.info(\"put: {}\", survey);\n      surveyCollection.put(survey.getId(), survey);\n    } catch (GSException e) {\n      e.printStackTrace();\n    }\n    return survey.getId();\n  }<\/code><\/pre>\n<\/div>\n<ul>\n<li><code>getSurvey<\/code>: For finding rows from GridDB, first we build TQL (a query language used by GridDB) with parameter <code>surveyId<\/code>, then create Query object to execute the TQL <code>surveyCollection.query(tql)<\/code>. To get the set of rows we call the <code>fetch()<\/code> method.<\/li>\n<\/ul>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">  public SurveyDto getSurvey(String surveyId) {\n    String tql = String.format(\"select * from surveys where id='%s'\", surveyId);\n    List&lt;surveydto> surveyDtos = query(tql, true);\n    if (surveyDtos == null || surveyDtos.size() == 0) {\n      throw new ResponseStatusException(NOT_FOUND, \"Not found\");\n    }\n    return surveyDtos.get(0);\n  }\n\n  public List&lt;\/surveydto>&lt;surveydto> getSurveys() {\n    String tql = \"select * from surveys limit 50\";\n    return query(tql, false);\n  }\n\n  private List&lt;\/surveydto>&lt;surveydto> query(String tql, boolean includeQuestion) {\n    List&lt;\/surveydto>&lt;surveydto> result = new ArrayList&lt;>();\n    Query&lt;survey> query;\n    try {\n      query = surveyCollection.query(tql);\n      RowSet&lt;\/survey>&lt;survey> rs = query.fetch();\n      while (rs.hasNext()) {\n        Survey model = rs.next();\n        List&lt;questiondto> questions = new ArrayList&lt;>();\n        if (includeQuestion) questions = questionService.getQuestions(model.getId());\n        result.add(\n            SurveyDto.builder()\n                .id(model.getId())\n                .createdAt(model.getCreatedAt())\n                .description(model.getDescription())\n                .title(model.getTitle())\n                .isActive(model.isActive())\n                .questions(questions)\n                .build());\n      }\n    } catch (GSException e) {\n      e.printStackTrace();\n    }\n    return result;\n  }\n&lt;\/questiondto>&lt;\/survey>&lt;\/surveydto><\/code><\/pre>\n<\/div>\n<h3>Serving Web Content with Spring MVC<\/h3>\n<p>Spring&#8217;s web MVC framework is, like many other web MVC frameworks, request-driven, designed around a central Servlet that dispatches requests to controllers and offers other functionality that facilitates the development of web applications. By using Spring MVC Framework we got the following advantages: * The Spring MVC separates each role, where the model object, controller, command object, view resolver, etc. can be fulfilled by a specialized object. * It uses a lightweight servlet container to develop and deploy your application. * It provides a robust configuration for both framework and application classes that includes easy referencing across contexts, such as from web controllers to business objects. * It provides the specific annotations that easily redirect the page.<\/p>\n<p>In this tutorial, we will follow a standard MVC architecture. We will have a controller (<code>SurveyWebController<\/code> class), views (<code>surveys.html<\/code> Thymeleaf template), and a model (a Java map object) for passing data into the view. Every method of the controller is mapped to a URI.<\/p>\n<h4>Surveys page<\/h4>\n<p>In the following example, <code>SurveyWebController<\/code>, method <code>listSurveys<\/code> handles GET requests for <code>\/surveys<\/code> by returning the name of a View (in this case, <code>surveys<\/code>), also adding attribute <code>surveys<\/code> to <code>Model<\/code> via its <code>addAttribute<\/code> method. To provide the attribute value (List of Survey) we call <code>surveyService.getSurveys()<\/code> method.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">@Controller\npublic class SurveyWebController {\n    \n  @GetMapping(\"\/surveys\")\n  public String listSurveys(Model model) {\n    model.addAttribute(\"surveys\", surveyService.getSurveys());\n    return \"surveys\";\n  }\n}\n<\/code><\/pre>\n<\/div>\n<p>After creating the controller class, we need to define the template for the views to be generated. We are using Thymeleaf, a modern server-side Java template engine for both web and standalone environments. The HTML templates written in Thymeleaf still look and work like HTML. In the following example, <code>surveys.html<\/code>, the model attributes can be accessed with the following syntax: <code>${attributeName}<\/code>, where the attributeName, in this case, is <code>surveys<\/code>. We define an HTML table for displaying a list of surveys and use <code>th:each<\/code> tag attribute to iterate over a collection of surveys, and <code>th:text<\/code> tag for displaying the value.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-html\">  &lt;div class=\"table-responsive\"&gt;\n  &lt;table class=\"table table-bordered\" id=\"dataTableSurvey\"&gt;\n    &lt;thead&gt;\n    &lt;tr&gt;\n      &lt;th scope=\"col\"&gt;#&lt;\/th&gt;\n      &lt;th scope=\"col\"&gt;Title&lt;\/th&gt;\n      &lt;th scope=\"col\"&gt;Description&lt;\/th&gt;\n      &lt;th scope=\"col\"&gt;Is Active&lt;\/th&gt;\n      &lt;th scope=\"col\"&gt;Created Date&lt;\/th&gt;\n    &lt;\/tr&gt;\n    &lt;\/thead&gt;\n    &lt;tbody&gt;\n    &lt;tr th_each=\"survey : ${surveys}\"&gt;\n      &lt;td&gt;\n        &lt;a class=\"nav-link\" th_href=\"@{\/responses\/{surveyId}(surveyId=${survey.id})}\"&gt;Answer&lt;\/a&gt;\n      &lt;\/td&gt;\n      &lt;td&gt;\n        &lt;a class=\"nav-link\" th_href=\"@{\/surveys\/{surveyId}\/responses(surveyId=${survey.id})}\" th_text=\"${survey.title}\"&gt;&lt;\/a&gt;\n      &lt;\/td&gt;\n      &lt;td th_text=\"${survey.description}\"&gt;&lt;\/td&gt;\n      &lt;td th_text=\"${survey.isActive}? 'Yups': 'No'\"&gt;&lt;\/td&gt;\n      &lt;td th_text=\"${survey.createdAt}\"&gt;&lt;\/td&gt;\n    &lt;\/tr&gt;\n    &lt;\/tbody&gt;\n  &lt;\/table&gt;\n&lt;\/div&gt;<\/code><\/pre>\n<\/div>\n<ul>\n<li>For answering the survey we provide an answer link in the table.<\/li>\n<li>For viewing the response list we can navigate through the survey title. From the response list, we can navigate to the answer.<\/li>\n<\/ul>\n<p>Here is a preview of the survey list page.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/1_survey_list.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/1_survey_list.png\" alt=\"\" width=\"1883\" height=\"563\" class=\"aligncenter size-full wp-image-29913\" srcset=\"\/wp-content\/uploads\/2024\/01\/1_survey_list.png 1883w, \/wp-content\/uploads\/2024\/01\/1_survey_list-300x90.png 300w, \/wp-content\/uploads\/2024\/01\/1_survey_list-1024x306.png 1024w, \/wp-content\/uploads\/2024\/01\/1_survey_list-768x230.png 768w, \/wp-content\/uploads\/2024\/01\/1_survey_list-1536x459.png 1536w, \/wp-content\/uploads\/2024\/01\/1_survey_list-600x179.png 600w\" sizes=\"(max-width: 1883px) 100vw, 1883px\" \/><\/a><\/p>\n<h4>Chart page<\/h4>\n<p>Here is a preview of the chart page:<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/4_survey_chart_answer.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/4_survey_chart_answer.png\" alt=\"\" width=\"890\" height=\"788\" class=\"aligncenter size-full wp-image-29918\" srcset=\"\/wp-content\/uploads\/2024\/01\/4_survey_chart_answer.png 890w, \/wp-content\/uploads\/2024\/01\/4_survey_chart_answer-300x266.png 300w, \/wp-content\/uploads\/2024\/01\/4_survey_chart_answer-768x680.png 768w, \/wp-content\/uploads\/2024\/01\/4_survey_chart_answer-600x531.png 600w\" sizes=\"(max-width: 890px) 100vw, 890px\" \/><\/a><\/p>\n<h3>Running the Project with Docker Compose<\/h3>\n<p>To spin up the project we will utilize Docker, a popular container engine. Containers help ensure that the application runs as expected on any machine. Docker gives us access to Docker Compose, a tool we can use to orchestrate multiple containerized applications together.<\/p>\n<ul>\n<li><code>dev.Dockerfile<\/code>: We use a Maven docker image with JDK21 <\/li>\n<\/ul>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">FROM maven:3.9.5-eclipse-temurin-21-alpine\nRUN mkdir \/app\nWORKDIR \/app\n\nCOPY pom.xml .\/\nRUN mvn dependency:go-offline\n\nCOPY docker-entrypoint-dev.sh .\/\nCOPY src .\/src<\/code><\/pre>\n<\/div>\n<ul>\n<li><code>docker-entrypoint-dev.sh<\/code> : in this script, we want to compile the code every time the code changes<\/li>\n<\/ul>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">#!\/bin\/bash\nexport TERM=xterm\necho \"wait 5s\"\nsleep 5\n\nmvn spring-boot:run -Dspring-boot.run.jvmArguments=\"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005\" &\n\nwhile true; do\n    watch -d -t -g \"ls -lR . | sha1sum\" && mvn compile\ndone<\/code><\/pre>\n<\/div>\n<ul>\n<li><code>docker-compose-dev.yml<\/code><\/li>\n<\/ul>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">version: '3.3'\nservices:\n  survey-app-dev:\n    container_name: survey-app-dev\n    build:\n      context: .\/\n      dockerfile: dev.Dockerfile\n    volumes:\n      - .\/src:\/app\/src\n      - .\/.m2:\/root\/.m2\n    environment:\n      - GRIDDB_NOTIFICATION_MEMBER=griddb-dev:10001\n      - GRIDDB_CLUSTER_NAME=dockerGridDB\n      - GRIDDB_USER=admin\n      - GRIDDB_PASSWORD=admin\n      - spring.thymeleaf.prefix=file:src\/main\/resources\/templates\/\n    command: sh .\/docker-entrypoint-dev.sh\n    ports:\n      - 8080:8080\n      - 35729:35729\n      - 5005:5005\n    networks:\n      - griddb-dev-net\n    depends_on:\n      - griddb-dev\n\n  griddb-dev:\n    container_name: griddb-dev\n    build:\n      context: .\/dockergriddb\n      dockerfile: Dockerfile\n    volumes:\n      - griddb-dev-vol:\/var\/lib\/gridstore\n    ports:\n      - 10001:10001\n    networks:\n      - griddb-dev-net\n\nnetworks:\n  griddb-dev-net:\nvolumes:\n  griddb-dev-vol:<\/code><\/pre>\n<\/div>\n<p>Then run the following commands:<\/p>\n<ol>\n<li>Build the docker image:<\/li>\n<\/ol>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">  docker compose -f .docker-compose-dev.yml build<\/code><\/pre>\n<\/div>\n<ol>\n<li>Run the docker image:<\/li>\n<\/ol>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">  docker compose -f .docker-compose-dev.yml up up<\/code><\/pre>\n<\/div>\n<p>The website available at http:\/\/localhost:8080<\/p>\n<h2>Conclusion<\/h2>\n<p>We have learned how to make a web-based survey platform using Spring Boot and GridDB as a database. We also learned how to develop using Docker Compose. With the appropriate use of Docker and Docker Compose, we can easily port entire development environments to other developer&#8217;s machines with minimal local environment configuration, including a local database, and a website. For the next iteration, we can add more functionality such as security, user management, and surveys management, and provide more analytics use cases. The repo for this project can be found <a href=\"https:\/\/github.com\/alifruliarso\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What is a survey platform? A survey is a research method used to collect data from a group of people. It is a tool that can be used to gather information about opinions, behaviors, and other characteristics of a population. Surveys can be conducted in various ways, such as through interviews, questionnaires, or online forms. [&hellip;]<\/p>\n","protected":false},"author":41,"featured_media":29919,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-46788","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Developing a Web-Based Survey Platform with Java Spring Boot: A Beginner\u2019s Guide | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"What is a survey platform? A survey is a research method used to collect data from a group of people. It is a tool that can be used to gather information\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Developing a Web-Based Survey Platform with Java Spring Boot: A Beginner\u2019s Guide | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"What is a survey platform? A survey is a research method used to collect data from a group of people. It is a tool that can be used to gather information\" \/>\n<meta property=\"og:url\" content=\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/\" \/>\n<meta property=\"og:site_name\" content=\"GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/griddbcommunity\/\" \/>\n<meta property=\"article:published_time\" content=\"2024-01-26T08:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-13T20:56:51+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/DevelopingWeb-BasedSurveySystemSpringBoot.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2240\" \/>\n\t<meta property=\"og:image:height\" content=\"1260\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"griddb-admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:site\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"griddb-admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/\"},\"author\":{\"name\":\"griddb-admin\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\"},\"headline\":\"Developing a Web-Based Survey Platform with Java Spring Boot: A Beginner\u2019s Guide\",\"datePublished\":\"2024-01-26T08:00:00+00:00\",\"dateModified\":\"2025-11-13T20:56:51+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/\"},\"wordCount\":1770,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2024\/01\/DevelopingWeb-BasedSurveySystemSpringBoot.png\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/\",\"url\":\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/\",\"name\":\"Developing a Web-Based Survey Platform with Java Spring Boot: A Beginner\u2019s Guide | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2024\/01\/DevelopingWeb-BasedSurveySystemSpringBoot.png\",\"datePublished\":\"2024-01-26T08:00:00+00:00\",\"dateModified\":\"2025-11-13T20:56:51+00:00\",\"description\":\"What is a survey platform? A survey is a research method used to collect data from a group of people. It is a tool that can be used to gather information\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2024\/01\/DevelopingWeb-BasedSurveySystemSpringBoot.png\",\"contentUrl\":\"\/wp-content\/uploads\/2024\/01\/DevelopingWeb-BasedSurveySystemSpringBoot.png\",\"width\":2240,\"height\":1260},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/griddb.net\/en\/#website\",\"url\":\"https:\/\/griddb.net\/en\/\",\"name\":\"GridDB: Open Source Time Series Database for IoT\",\"description\":\"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL\",\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/griddb.net\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/griddb.net\/en\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\/\/griddb.net\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/griddbcommunity\/\",\"https:\/\/x.com\/GridDBCommunity\",\"https:\/\/www.linkedin.com\/company\/griddb-by-toshiba\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\",\"name\":\"griddb-admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"caption\":\"griddb-admin\"},\"url\":\"https:\/\/griddb.net\/en\/author\/griddb-admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Developing a Web-Based Survey Platform with Java Spring Boot: A Beginner\u2019s Guide | GridDB: Open Source Time Series Database for IoT","description":"What is a survey platform? A survey is a research method used to collect data from a group of people. It is a tool that can be used to gather information","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/","og_locale":"en_US","og_type":"article","og_title":"Developing a Web-Based Survey Platform with Java Spring Boot: A Beginner\u2019s Guide | GridDB: Open Source Time Series Database for IoT","og_description":"What is a survey platform? A survey is a research method used to collect data from a group of people. It is a tool that can be used to gather information","og_url":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2024-01-26T08:00:00+00:00","article_modified_time":"2025-11-13T20:56:51+00:00","og_image":[{"width":2240,"height":1260,"url":"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/DevelopingWeb-BasedSurveySystemSpringBoot.png","type":"image\/png"}],"author":"griddb-admin","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"griddb-admin","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#article","isPartOf":{"@id":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/"},"author":{"name":"griddb-admin","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233"},"headline":"Developing a Web-Based Survey Platform with Java Spring Boot: A Beginner\u2019s Guide","datePublished":"2024-01-26T08:00:00+00:00","dateModified":"2025-11-13T20:56:51+00:00","mainEntityOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/"},"wordCount":1770,"commentCount":0,"publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2024\/01\/DevelopingWeb-BasedSurveySystemSpringBoot.png","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/","url":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/","name":"Developing a Web-Based Survey Platform with Java Spring Boot: A Beginner\u2019s Guide | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#primaryimage"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2024\/01\/DevelopingWeb-BasedSurveySystemSpringBoot.png","datePublished":"2024-01-26T08:00:00+00:00","dateModified":"2025-11-13T20:56:51+00:00","description":"What is a survey platform? A survey is a research method used to collect data from a group of people. It is a tool that can be used to gather information","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/blog\/developing-a-web-based-survey-platform-with-java-spring-boot-a-beginners-guide\/#primaryimage","url":"\/wp-content\/uploads\/2024\/01\/DevelopingWeb-BasedSurveySystemSpringBoot.png","contentUrl":"\/wp-content\/uploads\/2024\/01\/DevelopingWeb-BasedSurveySystemSpringBoot.png","width":2240,"height":1260},{"@type":"WebSite","@id":"https:\/\/griddb.net\/en\/#website","url":"https:\/\/griddb.net\/en\/","name":"GridDB: Open Source Time Series Database for IoT","description":"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL","publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/griddb.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/griddb.net\/en\/#organization","name":"Fixstars","url":"https:\/\/griddb.net\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/","url":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/griddbcommunity\/","https:\/\/x.com\/GridDBCommunity","https:\/\/www.linkedin.com\/company\/griddb-by-toshiba"]},{"@type":"Person","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233","name":"griddb-admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","caption":"griddb-admin"},"url":"https:\/\/griddb.net\/en\/author\/griddb-admin\/"}]}},"_links":{"self":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts\/46788","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/comments?post=46788"}],"version-history":[{"count":1,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts\/46788\/revisions"}],"predecessor-version":[{"id":51450,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts\/46788\/revisions\/51450"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/media\/29919"}],"wp:attachment":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/media?parent=46788"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/categories?post=46788"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/tags?post=46788"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}