How to call a static method in JSP/EL? - java

I'm new to JSP. I tried connecting MySQL and my JSP pages and it works fine. But here is what I needed to do.
I have a table attribute called "balance". Retrieve it and use it to calculate a new value called "amount". (I'm not printing "balance").
<c:forEach var="row" items="${rs.rows}">
ID: ${row.id}<br/>
Passwd: ${row.passwd}<br/>
Amount: <%=Calculate.getAmount(${row.balance})%>
</c:forEach>
It seems it's not possible to insert scriptlets within JSTL tags.

You cannot invoke static methods directly in EL. EL will only invoke instance methods.
As to your failing scriptlet attempt, you cannot mix scriptlets and EL. Use the one or the other. Since scriptlets are discouraged over a decade, you should stick to an EL-only solution.
You have basically 2 options (assuming both balance and Calculate#getAmount() are double).
Just wrap it in an instance method.
public double getAmount() {
return Calculate.getAmount(balance);
}
And use it instead:
Amount: ${row.amount}
Or, declare Calculate#getAmount() as an EL function. First create a /WEB-INF/functions.tld file:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<display-name>Custom Functions</display-name>
<tlib-version>1.0</tlib-version>
<uri>http://example.com/functions</uri>
<function>
<name>calculateAmount</name>
<function-class>com.example.Calculate</function-class>
<function-signature>double getAmount(double)</function-signature>
</function>
</taglib>
And use it as follows:
<%#taglib uri="http://example.com/functions" prefix="f" %>
...
Amount: ${f:calculateAmount(row.balance)}">

Another approach is to use Spring SpEL:
<%#taglib prefix="s" uri="http://www.springframework.org/tags" %>
<s:eval expression="T(org.company.Calculate).getAmount(row.balance)" var="rowBalance" />
Amount: ${rowBalance}
If you skip optional var="rowBalance" then <s:eval> will print the result of the expression to output.

If your Java class is:
package com.test.ejb.util;
public class CommonUtilFunc {
public static String getStatusDesc(String status){
if(status.equals("A")){
return "Active";
}else if(status.equals("I")){
return "Inactive";
}else{
return "Unknown";
}
}
}
Then you can call static method 'getStatusDesc' as below in JSP page.
Use JSTL useBean to get class at top of the JSP page:
<jsp:useBean id="cmnUtilFunc" class="com.test.ejb.util.CommonUtilFunc"/>
Then call function where you required using Expression Language:
<table>
<td>${cmnUtilFunc.getStatusDesc('A')}</td>
</table>

Bean like StaticInterface also can be used
<h:commandButton value="reset settings" action="#{staticinterface.resetSettings}"/>
and bean
package com.example.common;
import com.example.common.Settings;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "staticinterface")
#ViewScoped
public class StaticInterface {
public StaticInterface() {
}
public void resetSettings() {
Settings.reset();
}
}

EL 2.2 has inbuild mechanism of calling methods. More here: oracle site.
But it has no access to static methods. Though you can stil call it's via object reference. But i use another solution, described in this article: Calling a Static Method From EL

If you're using struts2, you could use
<s:var name='myVar' value="%{#package.prefix.MyClass#myMethod('param')}"/>
and then reference 'myVar' in html or html tag attribute as ${myVar}

Based on #Lukas answer you can use that bean and call method by reflection:
#ManagedBean (name = "staticCaller")
#ApplicationScoped
public class StaticCaller {
private static final Logger LOGGER = Logger.getLogger(StaticCaller.class);
/**
* #param clazz
* #param method
* #return
*/
#SuppressWarnings("unchecked")
public <E> E call(String clazz, String method, Object... objs){
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
final List<Class<?>> clasesparamList = new ArrayList<Class<?>>();
final List<Object> objectParamList = new ArrayList<Object>();
if (objs != null && objs.length > 0){
for (final Object obj : objs){
clasesparamList.add(obj.getClass());
objectParamList.add(obj);
}
}
try {
final Class<?> clase = loader.loadClass(clazz);
final Method met = clase.getMethod(method, clasesparamList.toArray(new Class<?>[clasesparamList.size()]));
return (E) met.invoke(null, objectParamList.toArray());
} catch (ClassNotFoundException e) {
LOGGER.error(e.getMessage(), e);
} catch (InvocationTargetException e) {
LOGGER.error(e.getMessage(), e);
} catch (IllegalAccessException e) {
LOGGER.error(e.getMessage(), e);
} catch (IllegalArgumentException e) {
LOGGER.error(e.getMessage(), e);
} catch (NoSuchMethodException e) {
LOGGER.error(e.getMessage(), e);
} catch (SecurityException e) {
LOGGER.error(e.getMessage(), e);
}
return null;
}
}
xhtml, into a commandbutton for example:
<p:commandButton action="#{staticCaller.call('org.company.Calculate', 'getAmount', row.balance)}" process="#this"/>

<c:forEach var="row" items="${rs.rows}">
ID: ${row.id}<br/>
Passwd: ${row.passwd}<br/>
<c:set var="balance" value="${row.balance}"/>
Amount: <%=Calculate.getAmount(pageContext.getAttribute("balance").toString())%>
</c:forEach>
In this solution, we're assigning value(Through core tag) to a variable and then we're fetching value of that variable in scriplet.

In Struts2 or Webwork2, you can use this:
<s:set name="tourLanguage" value="#foo.bar.TourLanguage#getTour(#name)"/>
Then reference #tourLanguage in your jsp

Related

Calling bean method on jsp

I'm trying to call a method that connects that is on a Bean on a jsp file. The method will make a request to a RMI Server and return a string. At this point the method is just return a pre-defined string for test.
This is the bean method:
public String getListProjects() throws RemoteException {
this.dataToSend = new Object[2];
this.dataToSend[1] = 0;
this.postCard = new ClientRequest("2", this.dataToSend, "tempo");
try{
this.postCard = this.connectToRMI.getActualProjects(this.postCard);
}catch(Exception e){
e.printStackTrace();
}
return "Hello";
}
And this is the jsp code:
<h1>Projectos Actuais</h1>
<h2><%
fundstarter.model.ConnectToRMIBean aux = new fundstarter.model.ConnectToRMIBean();
try{
aux.getListProjects();
}catch(Exception e){
e.printStackTrace();
}
%>
</h2>
I'm guiding my self from another code, and the method is called like this. But in my case it's not working, and I can't figure out what is wrong.
Since you've tagged this struts2, assuming the getListProjects() is on the Action, in JSP use:
<s:property value="listProjects" />
If instead it is on a bean, declare the bean in the Action, and expose it through a getter:
private MyBean bean;
public MyBean getBean(){
return bean;
}
and in JSP use the dot notation:
<s:property value="bean.listProjects" />
P.S: always avoid Scriptlets (<% %>), they're evil.
Quoting and fixing your latest change on edit with some comments:
<h1>Projectos Actuais</h1>
<h2><%
try{
fundstarter.model.ConnectToRMIBean aux = new fundstarter.model.ConnectToRMIBean();
//Send result into generated HTML page with out.print!
out.print(aux.getListProjects());
}catch(Exception e){
e.printStackTrace();
}
%>
</h2>
As per the flow of Struts there should be field in beanclass with same name of getter & setter. For an example if your method name is getListPorjects then in your bean class there should be a private string variable name listprojects.
Also your method will update with following to way to return listprojects.
example:
public String getListProjects() throws RemoteException {
this.dataToSend = new Object[2];
this.dataToSend[1] = 0;
this.postCard = new ClientRequest("2", this.dataToSend, "tempo");
try{
this.postCard = this.connectToRMI.getActualProjects(this.postCard);
listprojects = "hello"
}catch(Exception e){
e.printStackTrace();
}
return listprojects;
}
Calling bean variable should be with ID over the JSP page.
<jsp:useBean id="aux" class="com.path.to.ConnectToRMIBean" scope="request" />
----
yours stuff
-----
<h1>${aux.listProjects}
hope this will help you. good luck
You are just missing the way <% %> and <%= %> are used in JSP. to print in <% %> tags use
<% out.println("Your results"); %>
and for <%= %>
<%=
String.valueOf(1+2);
%>

Printing text to webpage inside a Java method in JSP

I have been struggling to print text inside a Java method on a Java server page. Here are some ways I've attempted to print the text and errors thrown from the Tomcat (Version 7.0.56) compiler:
<%
class Base {
public void main() {
String Text = "ThisIsText";
out.println(Text);
}
}
%>
Error: Cannot refer to the non-final local variable out defined in an enclosing
scope
<%
class Base {
static Text;
public void main() {
String Text = "ThisIsText";
}
out.println(Text);
}
%>
Syntax error, insert "Identifier (" to complete MethodHeaderName
<%
class Base {
static Text;
public String text() {
String Text = "NewText";
return Text;
}
}
%>
<%text();%>
The method text() is undefined for the type Base_jsp
Is there any way to print HTML Text directly from a Java method in a JSP scriptlet?
The out variable is already inside a method - _jspService. So if you are going to use out, declare another method that takes out as parameter using declaration - <%! and then just call this method.
Use a declarative tag instead
<%!
class Base {
JspWriter out;
public Base(JspWriter out) {
this.out = out;
}
public void main() {
String Text = "ThisIsText";
try {
out.println(Text);
} catch (Exception e) {
e.printStackTrace();
}
}
}
%>
<%(new Base(out)).main();%>
when you write something in <%%> the code between these tags is placed in methods so you cant declare function or class inside that tags because we cant have methods or class inside methods.
Similar,Also check

Freemarker - flat structure of passing parameters, transfer to array of objects

How to eval this kind of parameters or I need to pass JSON? I can change structure of parameters: "news[0].title" or "news.0.title" or anything else but I wouldn't like to ask users of my API to form json.
#Autowired
private TemplateEmailBodyPreparer preparer;
public void doIt() {
Map<String,String> properties = new HashMap<String,String>() {{
put("news[0].title", "Title 1");
put("news[0].body", "Body 1");
put("news[1].title", "Title 2");
put("news[1].body", "Body 2");
}};
String result = preparer.getByTemplate("mail/html/news.ftl", properties);
System.out.println("Result = " + result);
}
#Service
public class TemplateEmailBodyPreparer implements EmailBodyPreparer {
#Autowired
private Configuration freeMarkerConfiguration;
public String getByTemplate(String templatePath, Map<String,String> properties) {
try {
Template template = freeMarkerConfiguration.getTemplate(templatePath, "UTF-8");
return FreeMarkerTemplateUtils.processTemplateIntoString(template, properties);
} catch (IOException | TemplateException e) {
throw new IllegalArgumentException("Unable to build template: " + e.getMessage());
}
}
}
mail/html/news.ftl
<!DOCTYPE html>
<html>
<head></head>
<body>
<#list news as content>
${content.title} - ${content.body}
</#list>
</body>
</html>
Error:
Caused by: java.lang.IllegalArgumentException: Unable to build template: The following has evaluated to null or missing:
==> news [in template "mail/html/news.ftl" at line 5, column 11]
In your example template FreeMarker expects a real List for news, and real Map-s or JavaBeans as the items in that list. It won't interpret those key values, written in some adhoc language (how could it?). Since you know the syntax of the keys, you will have to parse them to List-s and Map-s, and then pass the result to FreeMarker.

Object suddenly missing from HttpServletRequest

I print a list directly in the servlet using the print writer and the list prints.
When I try to put in the jsp however the list doesn't print whether I use JSTL or scriptlets.
I tried to test in JSTL and scriptlet if the object is null and turns out that it is!
Why does this happen and how can I fix this?
Servlet code that works
for (Artist artist:artists){
resp.getWriter().println(artist.getName());
}
Servlet code that puts object in the request
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("com/helloworld/beans/helloworld-context.xml");
ArtistDao artistDao = (ArtistDao) ctx.getBean("artistDao");
List<Artist> artists = null;
try {
artists = artistDao.getAll();
} catch (SQLException e) {
e.printStackTrace();
}
req.setAttribute("artists", artists);
try {
req.getRequestDispatcher("index.jsp").forward(req, resp);
} catch (ServletException e) {
e.printStackTrace();
}
scriptlet code that suddenly finds the object null
<%
List<Artist> artists = (List<Artist>) request.getAttribute("artists");
if (artists == null) {
out.println("artists null");
}
else {
for (Artist artist: artists){
out.println(artist.getName());
}
}
%>
Even the jstl code seems to agree
<c:if test="${artists eq null}">
Artists are null
</c:if>
<c:forEach var="artist" items="${artists}">
${artist.name}
</c:forEach>
For my app I am using weblogic, spring 2.5.6 and ibatis.
I think it depends on the web server. But without changing your previous directory structure,
try putting the list in session like this
req.getSession(false).setAttribute("artists", artists);
and in your jsp,
write
List<Artist> artists = (List<Artist>) request.getSession(false).getAttribute("artists");
I think my approach will work for all web servers.
Maybe the app server is resetting your request object. You can work around this by creating a new request object, that wraps your original request, and pass that to the reqest dispatcher.
e.g.
MyHttpRequest myRequest = new MyHttpRequest(req);
myRequest.setAttribute(...);
req.getRequestDispatcher("index.jsp").forward(myRequest, resp);
And the MyHttpReqest code:
class MyHttpRequest extends HttpServletRequestWrapper
{
Map attributes = new HashMap();
MyHttpRequest(HttpRequest original) {
super(original);
}
#Override
public void setAttribute(Object key, Object value) {
attributes.put(key, value);
}
public Object getAttribute(Object key) {
Object value = attributes.get(key);
if (value==null)
value = super.getAttribute(key);
return value;
}
// similar for removeAttribute
}
I just discovered inadvertently while trying to fix my directory structure in WebContent/
My previous directory structure was
WEB-CONTENT/
- META-INF/
- WEB-INF/
index.jsp
Then I tried to create a folder jsp in WEB-CONTENT and placed index.jsp there. It works!
My current directory structure now is
WEB-CONTENT/
- META-INF/
- WEB-INF/
- jsp/
-index.jsp
I don't know why it works but it did.
Anyone here with any idea why?

JSP helper class for printing content

I have a question on code reuse in JSP. I have a JSP page example.jsp that issues a call to a database and gets the results. I have a java class HelperClass.java that accepts a record and prints out the different fields
response.getWriter().println
Now my JSP page has HTML as well and the problem is the content printed out by the HelperClass appears before the content in the JSP page. E.g.
<body>
This is the first line <br/>
HelperClass.printdata("second line");
</body>
output is
secondline This is the first line
Is this a known issue. What is the best way to design an HelperClass for a JSP page that prints content out to the page. Any pointers would be greatly appreciated.
Just do not use a "HelperClass to print data". This makes no sense. There you have EL for.
${bean.property}
That's all. Use a servlet to control, preprocess and postprocess requests. Use taglibs (e.g. JSTL) and EL to access and display backend data.
Here's a basic kickoff example of a Servlet which preprocesses the request before display in JSP:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Person> persons = personDAO.list(); // Get list of persons from DB.
request.setAttribute("persons", persons); // So it's available as `${persons}` in EL.
request.getRequestDispatcher("/WEB-INF/persons.jsp").forward(request, response); // Forward to JSP for display.
}
Here, the Person is just a Javabean class which represents a real world entity.
public class Person {
private Long id;
private String name;
private String email;
private Integer age;
// Add/generate getters and setters here.
}
The PersonDAO#list() method just returns a List of Person objects from the DB:
public List<Person> list() throws SQLException {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
List<Person> persons = new ArrayList<Person>();
try {
connection = database.getConnection();
statement = connection.createStatement("SELECT id, name, email, age FROM person");
resultSet = statement.executeQuery();
while (resultSet.next()) {
Person person = new Person();
person.setId(resultSet.getLong("id"));
person.setName(resultSet.getString("name"));
person.setEmail(resultSet.getString("email"));
person.setAge(resultSet.getInteger("age"));
persons.add(person);
}
} finally {
if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
return persons;
}
Map the servlet in web.xml on an url-pattern of /persons. The JSP is hidden in /WEB-INF so that nobody can access it directly without requesting the servlet first (else one would get an empty table).
Now, here's how persons.jsp look like, it uses JSTL (just drop jstl-1.2.jar in /WEB-INF/lib) c:forEach to iterate over a List and it uses EL to access the backend data and bean properties. The servlet has put the List<Person> as request attribute with name persons so that it's available by ${persons} in EL. Each iteration in c:forEach gives a Person instance back, so that you can display their proeprties with EL.
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<table>
<c:forEach items="${persons}" var="person">
<tr>
<td>${person.name}</td>
<td>${person.email}</td>
<td>${person.age}</td>
</tr>
</c:forEach>
</table>
Call it by http://example.com/contextname/persons. That's all. No need for a "HelperClass to print data" ;) To learn more about JSTL, check Java EE tutorial part II chapter 7 and to learn more about EL, check Java EE tutorial part II chapter 5. To learn more about stuff behind PersonDAO, check this article.

Categories

Resources