Using jsp:setProperty to set one bean in other bean - java

I would like to know how to use jsp:setProperty in the following scenario. Here is a simple example of two java classes.
public class MyExample {
private MyName myNameExample = new MyName();
public MyExample() {}
public MyName getMyNameExample() {
return myNameExample;
}
public void setMyNameExample(MyName setTo) {
myNameExample = setTo;
}
}
public class MyName {
private String firstName;
public MyName() {}
public String getFirstName() {
return firstName;
}
public String setFirstName(String setTo) {
firstName = setTo;
}
}
I was trying to use something like:
<jsp:useBean id="example" class="MyExample" scope="page"/>
<jsp:setProperty name="example" property="????" value="aFirstName"/>
The important part here is that I want to reference the MyName object from within MyExample. Therefore, creating a bean to directly access MyName will not help me. So I am not looking for this answer:
<jsp:useBean id="name" class="MyName" scope="page"/>
<jsp:setProperty name="name" property="firstName" value="aFirstName"/>

You could just create both beans and set one in other by ${}.
<jsp:useBean id="myName" class="MyName" scope="page" />
<jsp:setProperty name="myName" property="firstName" value="aFirstName" />
<jsp:useBean id="myExample" class="MyExample" scope="page" />
<jsp:setProperty name="myExample" property="myExampleName" value="${myName}" />
Unrelated to the concrete problem, I'd suggest to invest time in learning servlets and MVC. The above is a pretty old fashioned and tight-coupled way of controlling the models in the view.
Note that using packageless classes may not work in all circumstances (since they are invisible for normal classes inside a package). Only in certain Apache Tomcat configurations it will work. Rather put your classes inside a package in order to be not dependent of that.

Related

struts2 form submit not hitting method

I have a .jsp form like so
<s:form action="AuditLogReport">Source IP<br>
<input type="text" class="auditLogSearch" name="sourceIp" value="All">
<input type="submit" value="Submit"/>
</s:form>
And my struts.xml is defined
<action name="AuditLogReport"
class="com.mycom.selfservice.actions.AuditLogAction" method="auditLogReport">
<result name="success">jsp/AuditLog.jsp</result>
<result name="error">jsp/Error.jsp</result>
</action>
Here is my class definition
public class AuditLogAction extends ActionSupport implements Action,ServletRequestAware {
And in my AuditLogAction class there is a method
public String auditLogReport() {
System.out.println("Im in auditLogReport...");
but when I click the button, auditLogReport method does not get hit. What I see in the browser url is http://localhost:7001/BPSelfServicePortal/AuditLogReport.action
It is appending .action which I think is why it doesn't find the method. So I tried putting
<constant name="struts.action.extension" value=""/>
in the struts.xml. That prevented the .action from being appended but the button still didn't work. Plus it caused the .css and images from being found. I have a link that uses the default execute() method and that works ok.
If I simply remove the .action in the url and hit enter, it hits the method but then none of the values in the form get passed.
Suggestions?
The problem turned out to be a Date parameter. Apparently struts2 doesn't like them.
public Date getFromDate() {
return fromDate;
}
public void setFromDate(Date fromDate) {
this.fromDate = fromDate;
}
Changed it to
public String getFromDate() {
return fromDate;
}
public void setFromDate(String fromDate) {
this.fromDate = fromDate;
}
And then it worked!

Spring-MVC: Get full-fledged object instead of string when using 'select-options'

I have the class Lesson, which holds the reference to Course object, like so:
public class Lesson {
...
private Course course;
...
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
...
}
And I want to set the Course property on the Lesson object through the select form:
<form:form method="post" action="addLesson" modelAttribute="lesson">
<form:select path="course">
<form:options items="${courses}"/>
</form:select>
<input type="submit" name="addLesson" value="Add lesson">
</form:form>
In my controller I have the following:
#Controller
public class LessonController {
#Autowired
private LessonRepository lessonRepository;
#Autowired
private CourseRepository courseRepository;
// form setup
#RequestMapping(value = "/", method = RequestMethod.GET)
public String showSchedule(ModelMap model) {
...
model.addAttribute("lesson", new Lesson());
model.addAttribute("courses", courseRepository.findAll());
...
}
#RequestMapping(value = "/addLesson", method = RequestMethod.POST)
public String addLesson(#ModelAttribute("lesson") Lesson lesson, BindingResult result) {
lessonRepository.save(lesson);
return "redirect:/";
}
...
}
The problem is that it passes the String representation of the Course object (defined by toString()) to the course setter of the Lesson object.
How do I properly set the Course property of the Lesson object using my select form?
Usually for UI rendering Formatter<T> is used with ConversionService. But prior to Spring 3, PropertyEditors were used.
I've shared sample github project for your case https://github.com/jama707/SpringSelectBoxSample
#Component("courseFormatter")
public class CourseFormatter implements Formatter<Course> {
private CourseRepository courseRepository=new CourseRepository();
#Override
public String print(Course course, Locale arg1) {
return course.getName();
}
#Override
public Course parse(String actorId, Locale arg1) {
return courseRepository.getCourse(actorId);
}
}
According to spring documentation you need to set itemValue and itemLabelon the form:options tag, otherwise ,as you already mentioned, the value will be the toString() of the Object, itemValue and itemLable should refer to properties from your Course bean.
Assuming that your Course class has a property name, then your form should look like this:
<form:form method="post" action="addLesson" modelAttribute="lesson">
<form:select path="course">
<form:options items="${courses}" itemValue="name" itemLabel="name"/>
</form:select>
<input type="submit" name="addLesson" value="Add lesson">
</form:form>
You can bind the course object directly instead of some course object property by using Spring Converters.
Implement the Converter interface which in your case may convert selected courseName to Course:
public class CourseConverter implements Converter<String, Course> {
public Course convert(String source) {
List<Course> courseList = //Populate courseList the way you did in Lesson
Course course = //Get course object based on selected courseName from courseList;
return course;
}
}
Now register the converter:
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean" >
<property name="converters">
<set>
<bean class="your.package.CourseConverter"/>
</set>
</property>
</bean>
and change your form:options as:
<form:options items="${courses}" itemValue="courseName" itemLabel="courseName"/>

jsp:useBean doesn't get a property value from a bean object

i'm trying to get a property value from a bean object inside jsp using standard actions,the initial html form go to a servlet which sets a value inside the desired property,sets the attribute inside the request object and then forwards it to the jsp page, the jsp gets the value from the property by using standard actions but it gets null!:
the bean object:
public class dog {
private String bread;
public String getBread() {
return bread;
}
public void setBread(String bread) {
this.bread = bread;
}
}
the servlet:
dog d=new dog();
d.setBread("Kizer");
request.setAttribute("bread", d);
RequestDispatcher view=request.getRequestDispatcher("index.jsp");
view.forward(request, response);
the JSP (index):
< id="person" class="com.example.model.dog" scope="request" />
Person created by servlet: <jsp:getProperty name="person" property="bread" />
why it returns null ?
In your JSP use
<jsp:useBean id="bread" class="com.example.model.dog" scope="request" />
<jsp:getProperty name="bread" property="bread" />
Using bean id atrribute is the same as bean object.

Getting a GET request param into an #ViewScoped bean

I have a (request-scoped) list from which the user may select a "PQ" (list of links). When clicked or otherwise entered into the browser the main page for each PQ shall be displayed. Each PQ's page is of the form
http://localhost:8080/projectname/main.jsf?id=2
Here's the PQ bean first:
#Named
#ViewScoped
public class PqHome implements Serializable
{
#PersistenceContext(unitName="...")
private EntityManager em;
private Integer id;
private PQ instance;
#PostConstruct
public void init()
{
System.out.println("ID is " + id); // ID from URL param
instance = em.find(PQ.class, id);
}
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public PQ getInstance()
{
return instance;
}
}
Here's the main.xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
...>
<ui:define name="metadata">
<f:metadata>
<f:viewParam name="id" value="#{pqHome.id}">
<f:convertNumber integerOnly="#{true}" />
</f:viewParam>
<!--f:event type="preRenderView" listener="#{pqHome.init}" /-->
</f:metadata>
</ui:define>
<ui:define name="title">
<h:outputText value="Main" />
</ui:define>
...
</ui:composition>
Any time I select or otherwise refresh the page/URL I get a NullPointerException from the EntityManager:
org.jboss.weld.exceptions.WeldException: WELD-000049 Unable to invoke [method] #PostConstruct public de.mycomp.myproj.beans.PqHome.init() on de.mycomp.myproj.beans.PqHome#4f0ea68f
at org.jboss.weld.bean.AbstractClassBean.defaultPostConstruct(AbstractClassBean.java:595)
...
Caused by: java.lang.IllegalArgumentException: id to load is required for loading
at org.hibernate.event.spi.LoadEvent.<init>(LoadEvent.java:87)
at org.hibernate.event.spi.LoadEvent.<init>(LoadEvent.java:59)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:961)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:957)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:787)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:762)
at org.jboss.as.jpa.container.AbstractEntityManager.find(AbstractEntityManager.java:221)
at de.mycomp.myproj.beans.PqHome.init(PqHome.java:47)
... 56 more
[Line 47 is em.find(...)]
The line
<f:event type="preRenderView" listener="#{pqHome.init}" />
doesn't make things any better. I'm pretty desparate now.
How do you get URL GET request params into an #ViewScoped bean?
Note: I bet it's not a trivial thing to do. Chances are I'm doing something wrong here conceptually, so any tips on how to improve are welcome. I felt that I needed to choose #ViewScoped because there will be more complex AJAX-based GUI on that page which I'd really like to keep accessible via URL GET params.
Thanks
There is a better way to get id from url. Just use it in #PostConstruct init() method to get "id" from url:
FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");
You can still use ViewScoped and #PostConstruct.
The #PostConstruct is invoked directly after bean's construction and all dependency injection (such as #PersistenceContext, #EJB, #ManagedProperty, #Inject, etc..etc..).
The <f:viewParam> sets its value during the update model values phase, which is far after (post)construction of the bean. So inside the #PostConstruct the <f:viewParam> value is simply not yet been set. It'll be still null at that point.
You're close with <f:event type="preRenderView">, but you have to remove the #PostConstruct annotation.
So:
<f:viewParam name="pq" value="#{pqHome.id}">
<f:convertNumber integerOnly="#{true}" />
</f:viewParam>
<f:event type="preRenderView" listener="#{pqHome.init}" />
with
private Integer id;
public void init() {
instance = em.find(PQ.class, id);
}
Unrelated to the concrete problem, I'd suggest to use a Converter for this instead. See also Communication in JSF 2.0 - Converting and validating GET request parameters.
Also the combination #Named #ViewScoped won't work as intended. The JSF-specific #ViewScoped works in combination with JSF-specific #ManagedBean only. Your CDI-specific #Named will behave like #RequestScoped this way. Either use #ManagedBean instead of #Named or use CDI-specific #ConversationScoped instead of #ViewScoped.

how to move a variable's value from jsf's bean page (i.e, bean.java) to another java class?

how to move a variable's value from jsf's bean page (i.e, bean.java) to another java class? when i tried to do that, the value assinged to the variable in the second java class is NULL.,
I have used primefaces UI framework(something like jsf) and assigned every fields value in to a bean class. the value assigned to every variable in bean class is proper. but when i tried to move those values to another .java file. The scope of the variable dies, and the value is NULL. Check out my codings..
LOGIN.XHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head></h:head>
<h:body>
<p:panel header="Login" style="">
<h:form>
<h:panelGrid columns="2" cellpadding="2">
<h:outputText value="Username"></h:outputText>
<p:inputText id="userName" value="#{loginBean.userName}"></p:inputText>
<h:outputText value="Password"></h:outputText>
<p:password id="password" value="#{loginBean.password}"></p:password>
<p:commandButton value="Sign in" ajax="false" actionListener="#{loginBean.forward}"></p:commandButton>
</h:panelGrid>
</h:form>
</p:panel>
</h:body>
</html>
loginBean.java
package bean;
import receive.*;
public class loginBean {
public String userName;
public String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void forward()
{
System.out.println(getUserName());
receiveclass r=new receiveclass();
r.dbc();
}
}
receiveclass.java
package receive;
import bean.loginBean;
public class receiveclass {
loginBean lb=new loginBean();
public void dbc()
{
String s= lb.getUserName();
String p=lb.getPassword();
System.out.println(s);
System.out.println(p);
//System.out.println("hi");
}
}
output is,
if i give as admin, admin in text fields
i am receiving as
admin
null
null
You're manually creating the beans instead of letting JSF manage the beans. Manually created beans won't be used by JSF at all. You need to let JSF auto-create and manage those beans. You can access other JSF managed beans by injecting it as #ManagedProperty:
In your particular case, the following should work:
#ManagedBean
#RequestScoped
public class LoginBean {
private String userName;
private String password;
#ManagedProperty
private ReceiveClass receiveClass;
public void forward() {
receiveClass.dbc(this);
}
// Add/generate getters and setters.
}
with
#ManagedBean
#SessionScoped
public class ReceiveClass {
public void dbc(LoginBean loginBean) {
System.out.println(loginBean.getUserName());
}
}
(Note that I fixed the code to adhere the Java Naming Conventions properly. Class names ought to start with uppercase)
See also:
Communication in JSF 2.0 - Injecting managed beans in each other
in your receiveclass you create a completely new instance of loginBean. Values can only be null.
I do it this way: I created a Java class in which I have static functions like this one
public class JSFHelper
{
public static Object getMyObject(String objname, Class<?> classname )
{
FacesContext fCtx = FacesContext.getCurrentInstance();
ELContext elCtx = fCtx.getELContext();
ExpressionFactory ef = fCtx.getApplication().getExpressionFactory();
ValueExpression ve =
ef.createValueExpression(elCtx, "#{" + objname+ "}",classname);
return (Object) ve.getValue(elCtx);
}
}
If I need a value from another Bean it would look like this in your receiveclass:
public class receiveclass
{
public void dbc()
{
loginBean lb=(loginBean)JSFHelper.getMyObject("loginBean",loginBean.class);
String s= lb.getUserName();
String p=lb.getPassword();
System.out.println(s);
System.out.println(p);
//System.out.println("hi");
}
}

Categories