An error happened during template parsing - spring-boot

Code
Order
public class Order {
private String id;
private BigDecimal amount;
//get set constructor constructors
}
IndexController
#Controller
public class IndexController {
#GetMapping
public String index() {
return "index";
}
}
OrderController
#Controller
#RequestMapping("/orders")
public class OrderController {
private final OrderService orderService;
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
#GetMapping
public Mono<String> list(Model model) {
var orders = orderService.orders();
model.addAttribute("orders", orders);
return Mono.just("orders/list");
}
}
OrderGenerator
public class OrderGenerator {
public Order generate() {
var amount = ThreadLocalRandom.current().nextDouble(1000.00);
return new Order(UUID.randomUUID().toString(), BigDecimal.valueOf(amount));
}
}
OrderService
#Service
public class OrderService {
private final Map<String, Order> orders = new ConcurrentHashMap<>(10);
#PostConstruct
public void init() {
var generator = new OrderGenerator();
for (int i = 0; i < 25; i++) {
var order = generator.generate();
orders.put(order.getId(), order);
}
}
public Mono<Order> findById(String id) {
return Mono.justOrEmpty(orders.get(id));
}
public Mono<Order> save(Mono<Order> order) {
return order.map(this::save);
}
private Order save(Order order) {
orders.put(order.getId(), order);
return order;
}
public Flux<Order> orders() {
return Flux.fromIterable(orders.values()).delayElements(Duration.ofMillis(128));
}
}
html
<body>
<h1>Orders</h1>
<table>
<thead>
<tr>
<th></th>
<th>Id</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr th:each="order : ${orders}">
<td th:text="${order.id}"></td>
<td th:text="${#numbers.formatCurrency(order.amount)}"
style="text-align: right"></td>
</tr>
</tbody>
</table>
</body>
error
An error happened during template parsing (template: "class path resource [templates/orders/list.html]")
Exception evaluating SpringEL expression: "order.id" (template: "orders/list" - line 19, col 9)
EL1008E: Property or field 'id' cannot be found on object of type 'reactor.core.publisher.FluxOnAssembly' - maybe not public or not valid?
I do not how to solve the problem, i hope you can help me.thanks for you reply.

You need to add reactive primitives like Flux and Mono as IReactiveDataDriverContextVariable.
IReactiveDataDriverContextVariable reactiveDataDrivenMode =
new ReactiveDataDriverContextVariable(orders);
model.addAttribute("orders", reactiveDataDrivenMode);

check that you are using spring-boot-starter-webflux instead of spring-boot-starter-web

Related

EL1008E: Property or field 'applicationName' cannot be found on object of type 'java.lang.String' - maybe not public or not valid?

Been stuck with this error for a while now.
EL1008E: Property or field 'applicationName' cannot be found on object of type 'java.lang.String' - maybe not public or not valid?
I'm trying to get the records from database through thymeleaf, but always gets this error. I think I've declared everything that is needed this.
Here's my code
Model
#Entity
#Table(name = "sms_alert", schema = "public")
public class SmsAlert {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "sms_id")
private Long smsId;
#Column(name = "application_name")
private String applicationName;
#Column(name = "sms_flag")
private String smsFlag;
public SmsAlert() {
}
public SmsAlert(String applicationName, String smsFlag) {
super();
this.applicationName = applicationName;
this.smsFlag = smsFlag;
}
public Long getSmsId() {
return smsId;
}
public void setSmsId(Long smsId) {
this.smsId = smsId;
}
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String getSmsFlag() {
return smsFlag;
}
public void setSmsFlag(String smsFlag) {
this.smsFlag = smsFlag;
}
}
Controller
#GetMapping(value = "/smsAlert/{applicationName}")
public String viewApplicationSmsAlert(#PathVariable("applicationName") String applicationName, Model model) {
System.out.println(applicationName);
model.addAttribute("sms", smsService.findSmsFlagByAppName(applicationName));
return "test";
}
Repository
#Repository
public interface SmsRepository extends JpaRepository<SmsAlert, Long> {
#Query(value = "SELECT s.application_name, s.sms_flag FROM public.sms_alert s WHERE s.application_name= :applicationName ", nativeQuery = true)
public String findSmsFlagByAppName(#Param("applicationName") String applicationName);
Service
#Service
public class SmsService {
#Autowired
private SmsRepository smsRepository;
public List<SmsAlert> findAll() {
return smsRepository.findAll();
}
public String findSmsFlagByAppName(String applicationName) {
return smsRepository.findSmsFlagByAppName(applicationName);
}
public void updateSmsFlag(String applicationName, String smsFlag) {
smsRepository.updateSmsFlag(applicationName, smsFlag);
}
}
HTML File
<body>
<div id="content">
<div>
<table class="table table-hover table-striped" id="invTable">
<thead>
<tr class="table-primary">
<th id="terminalId">Terminal ID</th>
</tr>
</thead>
<tbody>
<tr th:each="sms : ${sms}">
<td th:text="${sms.applicationName}"></td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
The findSmsFlagByAppName method in SmsRepository returns a String. Your controller is putting that String in the model with the variable name sms. Then in your view you are referencing ${sms.applicationName} which is trying to evaluate the applicationName property on that String, which of course does not exist.
You could make the error go away a number of ways. One is, populate the model withe applicationName as a String and then in the view simply refer to that String.
Another option is to rework the findSmsFlagByAppName method to return a SmsAlert.

Sping MVC and hibernate: undeclared variable in jsp become null when saved

I just created my simple web application using Spring frameworks and hibernate. But I face the crucial problem when there is a transaction with my database.
When I tried to update my object, undeclared variables become null when saved to the database.
I will explain it with an example.
Model.java:
public class Model implements Serializable {
private int id;
private String firstName;
private String lastName;
private String description;
//setter getter
}
ModelDaoImpl.java:
#Repository("modelDao")
public class ModelDaoImpl implements ModelDao {
#Autowired
SessionFactory sessionFactory;
public Model create (Model model) throws Exception {
this.sessionFactory.getCurrentSession().save(model);
return model;
}
public Model update (Model model) throws Exception {
this.sessionFactory.getCurrentSession().update(model);
return model;
}
public Model get (Serializable id) throws Exception {
return (Model) this.sessionFactory.getCurrentSession().get(Model.class, id);
}
}
ModelServiceImpl.java:
#Service("modelService")
public class ModelServiceImpl implements ModelService {
#Autowired
modelDao modelDao;
#Transactional
public Model create (Model model) throws Exception {
return modelDao.create(model);
}
#Transactional
public Model update (Model model) throws Exception {
return modelDao.udpdate(model);
}
#Transactional
public Model get (Serializable id) throws Exception {
return modelDao.get(id);
}
}
ModelController.java:
#Controller
public class ModelController {
#Autowired
ModelService modelService
#RequestMapping(value="/editModel", method.RequestMethod.GET)
public String formCreator(ModelMap model, HttpServletRequest request) {
Integer id = new Integer(request.getParameter("id"));
Model modelData = new Model();
if (id != null) {
modelData = modelService.get(id);
}
model.addAttribute("modelData", modelData);
return "editModel"
}
#RequestMapping(value="/saveModel", method.RequestMethod.POST)
public String saveData(#ModelAttribute("modelData") Model modelData) {
if (modelData.getId() == null) {
modelService.create(modelData);
} else {
modelService.update(modelData);
}
return "redirect:/modelList";
}
//SKIP FOR GET MODEL LIST AND GET MODEL DETAIL
}
editModel.jsp:
<form:form action="${pageContext.request.contextPath}/saveModel" method="POST" modelAttribute="modelData">
<table>
<form:hidden path="id"/>
<tr>
<td>First Name:</td>
<td><form:input path="firstName"/></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName"/></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="Save"></td>
</tr>
</table>
</form:form>
From jsp page we see that I didn't declare variable 'description', but when update my existing data the variable 'description' become null. I have tried using #DynamicUpdate or related to dynamic update process, but the result was still the same, the variable 'description' still become null.
Any suggestion?
The problem is that the way your controller is written: a new Model instance is created
and populated on execution of saveData.
You can update your code to be like the below. Now on POST the Model instance
will be that returned from getModel() rather than a new instance and only the
values specified in the incoming request wil be updated. We can also update the GET to use the same code to populate the model.
Essentially then:
on GET - the model will be populated for the UI by a call to #ModelAttribute
on POST - the model will be populated and the Model instance returned will be passed to saveData();
See:
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-modelattrib-method-args
#Controller
public class ModelController {
#Autowired
ModelService modelService
#RequestMapping(value="/editModel", method.RequestMethod.GET)
public String formCreator(HttpServletRequest request) {
return "editModel"
}
#RequestMapping(value="/saveModel", method.RequestMethod.POST)
public String saveData(#ModelAttribute("modelData") Model model) {
//you can have 1 method in your service and DAO
//DAO can use saveOrUpdate() method of session;
modelService.persist(model);
return "redirect:/modelList";
}
#ModelAttribute("modelData")
public Model getModel(#RequestParam(name = "id", required = false)Integer id){
return id != null ? modelService.get(id) : new Model();
}
}

Springboot and thymealf loop

hope you can help with this simple noob problem. I creating a Multiple choice question using springboot and thymeleaf.I am getting this error and hope you can help me write the controller method.
Error during execution of processor 'org.thymeleaf.spring4.processor.attr.SpringInputGeneralFieldAttrProcessor' (learning:23)
Neither BindingResult nor plain target object for bean name 'options[0]' available as request attribute
<form method="post" th:action="#{/list}" >
<table>
<tr th:each="option, rowStat : *{a}">
<td><input type="radio" th:field="*{options[__${rowStat.index}__].ansA}" th:value="A"/></td>
<td><input type="radio" th:field="*{options[__${rowStat.index}__].ansB}" th:value="B"/></td>
</tr>
</table>
<input type="submit" value="ok"/>
</form>
Model object
#Entity
public class LearningStyle {
private int Qid;
private String question;
private String ansA;
private String ansB;
public LearningStyle(int qid, String question, String ansA, String ansB) {
Qid = qid;
this.question = question;
this.ansA = ansA;
this.ansB = ansB;
}
public LearningStyle(){}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Qid", nullable = false, updatable = false)
public int getQid() {
return Qid;
}
public void setQid(int qid) {
Qid = qid;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getAnsA() {
return ansA;
}
public void setAnsA(String ansA) {
this.ansA = ansA;
}
public String getAnsB() {
return ansB;
}
public void setAnsB(String ansB) {
this.ansB = ansB;
}
}
Controller
public class LearningStyleController {
#Autowired
LearningStyleService learningstyleservice;
#RequestMapping("/list")
public String learningstyle(Model model) {
List<LearningStyle> a= learningstyleservice.findAll();
model.addAttribute("a",a);
return "learning";
}
#RequestMapping(value = "/list", method = RequestMethod.POST)
public String learn(#ModelAttribute("a") LearningStyle learningStyle, Model model) {
//code to get list of object
return "home";
}

JSTL Items not getting displayed

have a very simple question on JSTL tags.
I am using spring to fetch data from back-end and display in the JSP.
Have the following code. I am getting the items of the for each tag printed in the console. But the same items are not getting printed/displayed inside the table rows.
<table id="table_id" class="display">
<thead>
<tr>
<th>Movie Name</th>
<th>Movie Rating</th>
</tr>
</thead>
<tbody>
<c:forEach items="${model.movieslist}" var="movie">
<tr>
<td>${movie.name}</td>
<td>${movie.rating}</td>
</tr>
</c:forEach>
</tbody>
My spring controller class
public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
// TODO Auto-generated method stub
logger.info("returning hello view");
List<Movie> moviesList = DbManager.getInstance().getMovies();
ModelMap modelMap = new ModelMap();
modelMap.addAttribute("movieslist", moviesList);
return new ModelAndView("hello.jsp",modelMap);
}
Movie domain class
package springapp.domain;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document(collection = "movie")
public class Movie {
#Id
public String _id;
public String name;
public String getId() {
return _id;
}
public void setId(String _id) {
this._id = _id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getRating() {
return rating;
}
public void setRating(float rating) {
this.rating = rating;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public float rating;
public String date;
#Override
public String toString() {
// TODO Auto-generated method stub
return name;
}
}
First, your jsp should contain the following taglib
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
Second, you don't need to get it using ${model.moviesList}, modify it as follows:
<c:forEach items="${movieslist}" var="movie">

Stripes: I can pre-populate a form, but after submit the formBean is null

I can pre-populate my Stripes JSP form with an object, client in my case, but when I submit this form, my object is returning as null.
I have created a second "temp" object that is a parallel duplicate of client and this retains its values, so I can't see an issue passing an object in the request
My form is as follows :
<s:form beanclass="com.jameselsey.salestracker.action.ViewClientAction">
<s:hidden name="clientA" value="${actionBean.clientA}"/>
<s:hidden name="clientId" value="${actionBean.clientId}"/>
<table>
<tr>
<td>Name : </td>
<td><s:text name="client.name"/></td>
</tr>
<tr>
<td>Sector : </td>
<td><s:text name="client.sector"/></td>
</tr>
<!-- omitted some attirbutes, not needed here -->
</table>
</s:form>
My action looks like
public class ViewClientAction extends BaseAction
{
#SpringBean
ClientService clientService;// = new ClientService();
private Integer clientId;
private Client client;
private Client clientA;
public void setClient(Client client)
{
this.client = client;
}
public Integer getClientId()
{
return clientId;
}
public void setClientId(Integer clientId)
{
this.clientId = clientId;
}
public Client getClientA()
{
return clientA;
}
public void setClientA(Client clientA)
{
this.clientA = clientA;
}
public Client getClient()
{
return client;
}
#DefaultHandler
public Resolution quickView()
{
clientA = clientService.getClientById(clientId);
client = clientService.getClientById(clientId);
return new ForwardResolution("/jsp/viewClientQuickView.jsp");
}
public Resolution save()
{
clientService.persistClient(client);
return new ForwardResolution("/jsp/reports.jsp");
}
public Resolution viewClientInfo()
{
client = clientService.getClientById(clientId);
return new ForwardResolution("/jsp/viewClientClientInfo.jsp");
}
...
If I set a breakpoint at clientService.persistClient(client); I can see that ClientA has all of the original values of the object, yet client is nulled.
Have I missed something that binds the form bean to the client object in my action?
Thanks
Add this line in your JSP:
<s:hidden name="client" value="${actionBean.client}"/>
I got this scenario working by adding a #Before method to re-hydrate the nested object. After this, save works properly
#Before(stages = LifecycleStage.BindingAndValidation)
public void rehydrate() {
if (context.getRequest().getParameter("save")!=null){
this.domainObject = getHibernateSession().load(DomainObject.class, context.getRequest().getParameter("id"));
}
}
public void save(){
Session session=getHibernateSession();
session.update(domainObject);
session.commit();
//...
}

Resources