How to dynamically generate SVG image from java code in thymeleaf? - java

I am stuck at one point where I have to display a SVG image on the springboot webpage, which is generated from Graphviz code in Java.
Any help is highly appreciated.
This is my controller class.
#RequestMapping(value = "/e2emap", method = RequestMethod.GET)
public String getE2E_WebPage(Model model
#RequestParam(name = Query_refresh_param, required = false) String refreshInterval) throws IOException {
final var graph = graphGenerator.createGraph();
final String graphString = java.util.Base64.getEncoder().encodeToString(graph);
model.addAttribute("graphVariable", graphString);
model.addAttribute("graph", graph);
return "Dynamic";
Here is the Dynamic.html file.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset = "UTF-8" />
<link href="../static/css/styles.css" data-th-href="#{/css/styles.css}" rel="stylesheet" />
<title>SRE End-2-End flow</title>
</head>
<body>
<div class="title"><a class="a-sre-e2e" >SRE End-2-End Flow</a></div>
<meta http-equiv= "refresh" content = "15 " />
<p>
<form action="/e2emap" method="get">
<span class="variable-title">Target Environment</span>
<select class="variable-combobox-values" name="target_env" id="target_env" onchange="submit()">
<option th:each="env : ${environments}" th:text="${env}" th:selected="${env}==${targetEnv}">sample-env</option>
</select>
</form>
<h1 th:text="${targetEnv}">bla-bla</h1>
<span>
<img th:src="#{'data:graph/svg;base64' + ${graph}}"> </img> Image
</span>
</body>
</html>
Some points to specify:
method createGraph() is the main method that uses graphviz to generate the graph and returns the graph in byteArray[] form.
The html has a drop down list to select different values. On-click, it should display the graph, which is not happening at the moment.

Related

How to display search results MVC

I'm a beginner and I came across an anomaly that I cant comprehend. From my point of view everything seems to be fine but I keep getting the same empty response when I perform a search in my MVC WebApp.
Take a look at my code. Any help would be greatly appreciated.
MY CONTROLLER
#Controller
public class ControllerACP {
#RequestMapping("/search")
public String Homea(Model model, #RequestParam(name = "query") String search) {
model.addAttribute("clients", clientRepository.search(search));
System.out.println(clientRepository.search(search)); // TO DISPLAY CONTENT ON CONSOLE
System.out.println(search); // ALSO DISPLAY CONTENT ON CONSOLE
return "search";
}
}
MY REPOSITORY
public interface ClientRepository extends CrudRepository<Client, Integer> {
#Query(value = "select * from client where name LIKE ('%:?%')", nativeQuery = true)
Iterable <Client> search(String search);
}
MY HTML FILE
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SEARCH</title>
<meta content="Dashboard" property="og:title">
<meta content="Dashboard" property="twitter:title">
<meta content="width=device-width, initial-scale=1" name="viewport">
<meta content="Webflow" name="generator">
<link href="css/normalize.css" rel="stylesheet" type="text/css">
<link href="css/webflow.css" rel="stylesheet" type="text/css">
<link href="css/ui-login-teste.webflow.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="w-container">
<h1>Search results</h1>
<form action="/search" class="w-form">
<input type="search" class="w-input" autofocus="true" maxlength="256" name="query" placeholder="Search…" id="search">
<input type="submit" value="Search" class="w-button">
</form>
</div>
<div class="w-container" th:each="client, interator: ${clients}">
<a th:href="#{/crud-cliente/pagina-do-cliente/{id}(id=${client.id})}" class="table-content-link w-inline-block">
<div class="valida-table-field foto" >
<div class="table-image-wrapper avatar" th:style="'background-image: url('+#{${'/uploads/' + client.foto}}+')'"></div>
</div>
<div class="valida-table-field nome-admin" >
<div class="_20px" th:text="${client.name}">Nome Completo</div>
</div>
<div class="valida-table-field categoria _6">
<div class="_20px">[[${client.phone}]]</div>
</div>
<div class="valida-table-field categoria _6">
<div class="_20px">[[${client.email}]]</div>
</div>
<div class="valida-table-field categoria _6">
<div class="_20px">[[${client.creation_date}]]</div>
</div>
</a>
</div>
</body>
</html>
You can try this query:
#Query(value = "select * from client where name LIKE :search", nativeQuery = true)
Iterable <Client> search(#Param("search") String search);
I suggest you debug your code and run the query separately in SSMS. Then alter your query and finalize the one where you get your desired output.
Your query should have the searched text between %%. Something Like
#Query(value = "select * from client where name LIKE ('%"+ searchedText +"%')", nativeQuery = true)
I hope it helps.

How to fix "Exception evaluating SpringEL expression" error after submitting a variable Spring/Thymeleaf

I am using Spring Boot/Thymeleaf to create a form that accepts an email address, redirects to a results page that displays the accepted email and sends it to a third party API (authenticated with Oauth2). I am having trouble with the form portion, I am attempting to use Thymeleaf to accept the input to display it on the result.html page. I am receiving an error when trying to display it on the results page, full error is:
[THYMELEAF][http-nio-8080-exec-4] Exception processing template "result.html": Exception evaluating SpringEL expression: "signup.email" (template: "result.html" - line 10, col 4)
I was attempting to follow the examples provided here:
https://spring.io/guides/gs/handling-form-submission/
I have attempted to modify the controller from #PostMapping and #GetMapping to #RequestMapping and add commenting described in a workaround such as:
<!--/*#thymesVar id="signup" type="com.mainconfig.controller1"*/-->
Here is the signup.html code containing the form:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html>
<head>
<title>My Jmml</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body style="background-color: #2B2B2B">
<br /><br />
<h2 style="text-align:center">Contact Information</h2>
<!-- Input Form -->
<!--/*#thymesVar id="signup" type="com.mainconfig.controller1"*/-->
<form action="#" th:action="#{/signup}" th:object="${signup}" method="post">
<div align="center">
<label>Email Address</label><br /><br />
<!--/*#thymesVar id="email" type="String"*/-->
<input type="text" th:field="*{email}" placeholder="Email" required />
<br />
<br />
<input class="submitbutton" type='submit' value='Submit'/>
<br />
</div>
</form>
</body>
</html>
Results page that should display the email (result.html):
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thank you for your submission!</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Thank you for your submission!</h1>
<p th:text="'Email: ' + ${signup.email}" />
Submit another message
</body>
</html>
Controller:
#Controller
public class controller1 {
#RequestMapping (value = "/home")
public String home(Model model) {
return "index.html";
}
#RequestMapping(value = "/signup", method= RequestMethod.GET)
public String signupForm(Model model) {
model.addAttribute("signup", new emailInput());
return "signup.html";
}
#RequestMapping(value = "/signup", method= RequestMethod.POST)
public String signupSubmit(#ModelAttribute("email") emailInput email) {
return "result.html";
}
}
Expected output should be the email variable displayed on the results page after it being gathered in the signup form.
If you have a recommendation on how to better do what I am attempting, I am open to suggestions! I am very new to Spring/Thymeleaf but have had experience with Java/Jsp. Thank you for any help, please let me know if you need anything else to help!
Hopefully this will be a starting point for you.
Make sure you place the html files under /resources/templates.
I changed a bit your signup html and result.html as follows, they are still not perfect(avoid using inline styles and use an external stylesheet!):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title>My Jmml</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body style="background-color: #2B2B2B">
<br /><br />
<h2 style="text-align:center">Contact Information</h2>
<!-- Input Form -->
<!--/*#thymesVar id="signup" type="com.mainconfig.controller1"*/-->
<form th:action="#{/signup}" th:object="${signup}" method="post">
<div align="center">
<label>Email Address</label><br /><br />
<!--/*#thymesVar id="email" type="String"*/-->
<input type="text" th:field="*{email}" placeholder="Email" />
<br />
<br />
<input class="submitbutton" type="submit" value="Submit"/>
<br />
</div>
</form>
</body>
and the result.html looks like this
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title>Thank you for your submission!</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Thank you for your submission!</h1>
<p th:text="'Email: ' + ${email}" />
Submit another message
</body>
</html>
I also created a form object, add additional fields here if you want
public class SignUpForm {
//you can put some annotations here if you want for validating the email
//for e.g #NotEmpty or a #Pattern(regexp to validate the email)
private String email;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
and in the end your Controller. I pass the email from the signup post request to the result.html via a flash attribute:
#Controller
public class Controller1 {
#RequestMapping(value = "/signup", method= RequestMethod.GET)
public String signupForm(#ModelAttribute("signup") SignUpForm form) {
return "/signup";
}
#RequestMapping(value = "/signup", method= RequestMethod.POST)
public String signupSubmit(#ModelAttribute("signup") SignUpForm form, RedirectAttributes redirectAttributes) {
//validate form first -> check bindingResult documentation
//do what you need with your form object
redirectAttributes.addFlashAttribute("email", form.getEmail());
return "redirect:/result";
}
#RequestMapping(value = "/result", method= RequestMethod.GET)
public String result() {
return "/result";
}
}

How to send information of a checkbox from the view to the controller in Thymeleaf?

I'm trying to send the values of looped checbox for print them in the controller. When I press a button, I want the information of the selected checbox to be send to the controller and print it in the console, but when I press my button to send the information to the controller method, it throws me a NullPointerException.
My HTML look like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Select Cities</title>
<link rel="stylesheet" type="text/css" href="../css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row align-items-center">
<div class="col-4 mt-3">
<form action="">
<div class="form-check" th:each="names : ${namesOfCities}">
<label for="" class="form-check-label">
<input type="checkbox" name="lista" th:value="${names}" th:text="${names}">
</label>
</div>
Aceptar
</form>
</div>
<div class="col-8">
<div id="chart" style="height: 400px"></div>
</div>
</div>
</div>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-3d.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="../js/jquery-3.3.1.min.js"></script>
<script src="../js/popper.min.js"></script>
<script src="../js/bootstrap.min.js"></script>
</body>
</html>
Here in the HTML I create a checkbox for each element in the list sended by the controller.
I have two methods in the Controller, the first one:
#GetMapping("/selectCities")
public ModelAndView selectCities(Model model){
ModelAndView mav = new ModelAndView(ViewConstant.SELECT_CITIES);
//List<String> citiesNames = namesOfCities();
List<String> citiesNames = recortarList();
model.addAttribute("namesOfCities", citiesNames);
return mav;
}
This method shows the HTML view and send a List of String that contains cities names.
The second method looks like this:
#GetMapping("/showSelectedCities")
public ModelAndView showSelectedCities(#RequestParam(name = "lista", required = false)List<String> id){
ModelAndView mav = new ModelAndView(ViewConstant.SELECT_CITIES);
for(int x=0;x<id.size();x++){
System.out.println(id.get(x));
}
return mav;
}
In this I want to recive the names of the cities of the selected checkbox sended by the view and print them in the console, but when I try it throws me a NullPointerException. How is the correct form to send information from a checkbox to the controller?
You have used form but you are submitting information through a link which is not possible. To solve this problems :
1) Give an action to the form as :
2) And add submit button inside form.
here
3) Clicking on submit button you will be redirected to action url.
Now you would get information filled inside form.

Why am I getting null object after submitting form in Spring?

I am new to Spring and yesterday I created a simple app. I type book's title, author and genre and it saves it to List<Book>. Book.java contains private fields (title, author, genre).
So creating books and saving them to list works fine. Also I can view all books I have added. So it works fine. But now I want to create and delete them. So I have BookService.java that can add and delete books.
BookService.java
private List<Book> allBooks = new ArrayList<>();
public List<Book> getAllBooks() {
return allBooks;
}
public void addBook(String title, String author, String genre) {
allBooks.add(new Book(title, author, genre));
}
public void deleteBook(Book book) {
allBooks.remove(book);
}
This is stuff in my controller to delete books
#GetMapping("/books/delete")
public String deleteBook(Model model) {
model.addAttribute("BookList", bookService.getAllBooks()); // Works fine
return "delete";
}
#PostMapping("/books/delete")
public String deletedBook(#ModelAttribute Book book, Model model) {
System.out.println(book.getTitle()); // null
bookService.deleteBook(book); // can't delete null so nothing happens to the list
model.addAttribute("deletedBook", book);
return "deletedBookResult";
}
delete.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body>
<h2>Delete page</h2>
<div th:each="bookObj : ${BookList}"> <!-- BookList - all books I add using submit form -->
<form action="#" th:action="#{/books/delete}" th:object="${bookObj}" method="post"> <!-- I SEND bookObj -->
<input type="submit" th:value="${bookObj.title}"/> <!-- WORKS. I GET BOOK'S NAME ON THIS BUTTON-->
</form>
</div>
</body>
</html>
I use th:each="bookObj : ${BookList}". So bookObj is every book I add. That's why I use th:object=${bookObj}. There is a form for each book I added later. And it display's it's title on the button. But when I press it, I get null to IDEA's console and on webpage. Why?
Thank you in advance.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body>
<h2 th:text=" 'You have just deleted' + ${deletedBook.title}"></h2>
<!-- You have just deleted null -->
</body>
</html>
You are not sending anything in your form. Add some hidden fields:
<div th:each="bookObj : ${BookList}">
<form action="#" th:action="#{/books/delete}" method="post">
<input type="hidden" th:name="genre" th:value="${bookObj.genre}"/>
<input type="hidden" th:name="author" th:value="${bookObj.author}"/>
<input type="hidden" th:name="title" th:value="${bookObj.title}"/>
<input type="submit" th:value="${bookObj.title}"/>
</form>
</div>
Or if you don't want to expose your data in html, you can try to use some sort of session objects instead (Probably an overkill, but sometimes can be useful):
#GetMapping("/books/delete")
public String deleteBook(Model model, HttpSession session) {
session.setAttribute("BookList", new Book[]{
new Book("Title", "Tom","genre"),
new Book("Title 2", "Jerry","genre2")}
);
return "delete";
}
#PostMapping("/books/delete")
public String deletedBook(HttpSession session, Integer id, Model model) {
Book[] books = (Book[]) session.getAttribute("BookList");
Book book = books[id];
System.out.println(book);
model.addAttribute("deletedBook", book);
return "deletedBookResult";
}
And use it like:
<div th:each="bookObj, iter : ${session.BookList}">
<form action="#" th:action="#{/books/delete}" method="post">
<input type="hidden" th:name="id" th:value="${iter.index}"/>
<input type="submit" th:value="${bookObj.title}"/>
</form>
</div>

Use web service in background of HTML

I have a web service and a html page and i want to calculate two values and show on the third text field but this code shows me on the next page. Any one help me for my FYP.
My index.html
<!DOCTYPE html>
<html>
<head>
<title>TO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>JAX-RS</h1>
<form action="http://localhost:8080/ConnectingToNode/webapi/myresource?ID" method="post" target="_self">
<p>
Number1 : <input type="text" name="number1" />
</p>
<p>
Number2 : <input type="text" name="number2" />
</p>
<p>
Number3 : <input type="text" name="number3" />
</p>
<input type="submit" value="Add" />
<p>
Total : <input type="text" name="number3" />
</p>
</form>
</body>
</html>
My web service
#Path("myresource")
public class MyResource{
HashMap<String, String> map= new HashMap<String, String>();
#POST
#Produces(MediaType.TEXT_PLAIN)
public Response addNumber(
#FormParam("number1") int number1,
#FormParam("number2") int number2
) {
int total=number1+number2;
return Response.status(200).entity("Total : " + total).build();
}
}
You want perform an ajax call instead of submitting the form. So just build a javascript function e.g. using Jquery:
$.post("<your servlet here>", $("#y<ourFormIdHere>").serialize(),callback);
Where callback is a function like this:
function(data){
console.log("Data",data); // do what you want with response data
}
Off course you have to bind the $.post function to your form button.

Categories

Resources