I have a Stripes form using an Action bean.
I can store the data without any problem out of the form, but I did not find out how to prepopulate the form's data.
I have simplified my example to show what's not working.
My code under #Before is without any effect: the data dont go into the form.
How should I manage this approach?
myform.jsp:
...
<stripes:form beanclass="UserActionBean">
...
<stripes:text name="user" />
<stripes:submit name="store" value="Save" />
...
</stripes:form>
...
ActionBean:
public class UserActionBean implements ActionBean {
private String user;
#Before
public void init() {
user = "myuser";
}
#DefaultHandler
public Resolution store() {
...
}
}
You will need public getters and setters for Stripes to be able to read the value.
Although usually I would use the #DefaultHandler for the get, and then create a new handler for the save e.g. #HandlesEvent(value = "save") public Resolution save () {...
This might be crude, but I used a getter like Scary Wombat said and initialized the variable in the ActionBean. Or you could set its value in your handler that does the initial page display.
#Validate(required = true, on = {
"proceed"
})
private String tumblrUrl= "xyz.tumblr.com";
...
public String getTumblrUrl() {
return this.tumblrUrl;
}
public void setTumblrUrl(final String tumblrUrl) {
this.tumblrUrl = tumblrUrl;
}
Related
Say I have this custom Java class Club.java:
public class Club
{
private Integer id;
private String name;
/* getters, setters */
}
Now the jquery-ui autocomplete code:
var autocomplete = $('#clubs').autocomplete({
source: currentClubs
}).data("autocomplete");
if (autocomplete != undefined)
{
autocomplete._renderItem = function(ul, item) {
return $("<li>").attr('data-value', item.value).append(item.label).appendTo(ul);
};
}
where currentClubs is an array of JSON objects which correspond to the above Java class Club ( { value : club.id, label : club.name } ).
This works fine until I submit the form.
I am using Spring MVC Framework, here is my controller:
#RequestMapping(value = "someMapping", method = RequestMethod.POST)
public String someMethod(HttpSession session, Model model, #ModelAttribute("someForm") SomeForm form)
{
jada jada ...
}
where SomeForm contains a field private Club clubChoice. I would like to map my selected JSON Object to that field. How can I achieve this? Many thanks.
Well, it took me another 10 minutes to figure out how to do this.
I changed this part:
var autocomplete = $('#clubs').autocomplete({
source: currentClubs
}).data("autocomplete");
to this:
var autocomplete = $('#clubs').autocomplete({
source: currentClubs,
select: function (event, ui) {
$('#club-id').val(ui.item.id);
}
}).data("autocomplete");
where clubId is a hidden input:
<form:input path="club.name" name="club-name" id="club-name" />
<form:hidden path="club.id" name="club-id" id="club-id" />
First of all I'm newbie in Struts.
I've a class:
public class Articulo {
private int codigo;
private String descripcion;
public int getCodigo() {
return codigo;
}
public void setCodigo(int codigo) {
this.codigo = codigo;
}
public String getDescripcion() {
return descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
}
which is populated with values in a dispatcher. In the dispatcher I've
private Articulo articulo;
.......
public Articulo getArticulo() {
return articulo;
}
public void setArticulo(Articulo articulo) {
this.articulo = articulo;
}
There is also a JSP with
<s:property value="articulo"/>
which read ok the articulo. Also works articulo
<s:property value="articulo.codigo"/>
But now I want from that jsp forward the entire object articulo to another action.
I can do
<s:hidden name="articulo.codigo" value="%{articulo.codigo}"/>
<s:hidden name="articulo.descripcion" value="%{articulo.descripcion}"/>
and that works fine, but is there anyway to do something like
<s:hidden name="articulo" value="%{articulo}"/>
So, is there anyway to get the object from JSP without setting all the properties of it?
there are 2 points:
Problem: you can't transfer object using <s:hidden />, all the parameter, what are transfered with HTTP should be string. Since you cannot convert this object to String, you can't transfer it using HTTP either.
Solution: You can put your object into session, so that you can access it anytime you want. here is an EXAMPLE
Yes, you can transfer object in two ways either by parameter or store it in session and access it whenever you need it.
<jsp:forward page="URL" >
<jsp:param name="ParamName1" value="YourObject" />
</jsp:forward>
Visit here for more detail.
http://www.gulland.com/courses/jsp/actions/forward
Keeping the object information in sessions is usually the preferred method.
But an alternative option is to create your own Type Converter.
Create a type converter by extending StrutsTypeConverter. The
Converter's role is to convert a String to an Object and an Object to
a String.
By doing so, you could so something like <s:hidden name="articulo" value="%{articulo}"/>
Keep in mind this method is insecure as the object values will be printed out as String in the hidden tag and can be seen through the browser.
But the advantage is that this method works across different sessions if you have a need for such a thing.
When or where do entities get created?
Do they get created when the XHTML page loads and accesses the entities via the managed bean?
Or do they get automatically created in the managed bean?
Do we need to manually create it from the managed bean's constructor?
Please see the code below (some necessary code might not have been copied.)
The entity would be:
public class PersonalInfo implements Serializable {
#Size(max = 50)
#Column(name = "FIRST_NAME", length = 50)
private String firstName;
// some getters and setters
}
the web page would be:
<h:form>
<h:outputText value="first name"/>
<h:inputText value="#{personalInforController.personalInfo.firstName}" />
<h:commandButton value="hit me"
action="#{personalInforController.create}"
immediate="true"/>
</h:form>
and the backing bean would be:
#Named(value = "personalInfoController")
#SessionScoped
public class PersonalInforController {
#EJB
PersonalInfoFacade ejbFacade;
PersonalInfo personalInfo;
String defaultPage = "index";
public String create() {
try {
ejbFacade.create(personalInfo);
return "prepareCreate";
} catch (Exception e) {
return "success";
}
}
}
In the example code given, the create action indeed doesn't seem to be able to work. The entity must be created by the backing bean before that.
If it's a simple entity, either the constructor or an #PostConstruct method would work. For instance:
#Named(value = "personalInfoController")
#SessionScoped
public class PersonalInforController {
#EJB
PersonalInfoFacade ejbFacade;
PersonalInfo personalInfo;
String defaultPage = "index";
#PostConstruct
public void init() {
personalInfo = new PersonalInfo();
}
public String create() {
try {
ejbFacade.create(personalInfo);
return "prepareCreate";
} catch (Exception e) {
return "success";
}
}
Some notes about the code. It's highly suspicious, and most likely plain wrong, to declare your bean to be #SessionScoped. If personalInfo is being edited in two tabs or windows you'll be in a world of hurt. I suggest making your bean #ViewScoped (for CDI, there's a separate extension made by the Seam3 that enables this, if you can't/won't use this extension consider using #ManagedBean instead of #Named).
Also, you might want to declare your instance variables to be private and give ejbFacade a better name (e.g. personalInfoFacade). I also doubt whether immediate is necessary on the commandButton, and since the outputText is obviously a label for the given inputText, you might want to consider using outputLabel and the for attribute.
How can I dynamically change managed bean of "value" attribute? For example, I have h:inputText and, depending on typed-in text, managed bean must be #{studentBean.login} or #{lecturerBean.login}. In a simplified form:
<h:inputText id="loginField" value="#{'nameofbean'.login}" />
I tried to embed another el-expression instead of 'nameofbean':
value="#{{userBean.specifyLogin()}.login}"
but it doesn't worked out.
Polymorphism should rather be done in the model, not in the view.
E.g.
<h:inputText value="#{person.login}" />
with
public interface Person {
public void login();
}
and
public class Student implements Person {
public void login() {
// ...
}
}
and
public class Lecturer implements Person {
public void login() {
// ...
}
}
and finally in the managed bean
private Person person;
public String login() {
if (isStudent) person = new Student(); // Rather use factory.
// ...
if (isLecturer) person = new Lecturer(); // Rather use factory.
// ...
person.login();
// ...
return "home";
}
Otherwise you have to change the view everytime when you add/remove a different type of Person. This is not right.
Another way:
<h:inputText id="loginField1" value="#{bean1.login}" rendered="someCondition1"/>
<h:inputText id="loginField2" value="#{bean2.login}" rendered="someCondition2"/>
For some reason Hibernate seems to be keeping my session open and updating the object without me explicitely invoking a save/update/saveorupdate. I guess the session is staying open and it's beeing marked as dirty.
However this is not the desired behaviour, so what's the cleanest way to fix this?
The issue seems to occur because I store a phone number without formatting in the database but the getter of the object returns a formatted telephone number.
My flow:
go to a jsp => controller => service => dao
DAO getter function
if(userId != 0) {
return (User)dbFactory.get(User.class, userId);
}
return null;
The service just passes it to the controller and the controller puts te User object in the request scope. I display it on my JSP page using EL.
edit:
I added the following:
JSP:
<spring:bind path = "user.telephoneNumber">${user.telephoneNumber}</spring:bind>
Controller:
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, "telephoneNumber", new TelephoneNumberEditor(false));
}
The editor:
public class TelephoneNumberEditor extends PropertyEditorSupport {
private boolean isRequired = false;
public TelephoneNumberEditor(boolean isRequired) {
this.isRequired = isRequired;
}
public void setAsText(String text) throws IllegalArgumentException {
String s = null;
if (!this.isRequired && StringUtils.isBlank(text)) {
setValue("");
}
else
{
s = text.replace("(0)","");
s = s.replaceAll("[^0-9]", "");
setValue(s);
}
}
public String getAsText() {
String telephoneNumber = (String) getValue();
if(StringUtils.isBlank(telephoneNumber)){
return "";
} else {
try {
MaskFormatter formatter = new MaskFormatter("+AA AA AA AA AA");
formatter.setValueContainsLiteralCharacters(false);
return formatter.valueToString(telephoneNumber);
} catch (ParseException e) {
return "";
}
}
}
}
And in the controller I put the User object in the request scope as user.
You can create another property (getter and setter) for the formatted value and mark it as transient (with #Transient or by omitting it in your .hbm.xml):
#Transient
public String getFormattedPhoneNumber() { ... }
public void setFormattedPhoneNumber(String number) { ... }
Alternatively, you can configure Hibernate access type to work with fields instead of properties - in that case your getters can return arbitrary representations.
EDIT: If you use Spring MVC databinding, you can implement your formatting logic in PropertyEditor. Since formatting a phone number is a presentation concern, moving it to the presentation layer looks reasonable:
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, "phoneNumber",
new PropertyEditorSupport() { ... });
}
In this approach custom editor works automatically in the typical Spring from processing cycle (form is rendered with Spring form tags and data are bound to #ModelAttribute upon POST). If you need to display formatted value manually (outside of form tags), you can use <spring:bind>:
<spring:bind path = "user.phoneNumber">${status.displayValue}</spring:bind>
(or without user. if inside <form:form>, I guess)
If you want to make non-persistent changes to a persistent object you can explicitly kick it out of context with Session.evict(Object object). Hibernate will not persist any changes you make to it after that's done.
Something about the description of why it happens doesn't quite add up. Are you using property based access for persistence, and not using direct getters-setters? A getter that marks up the value might raise architectural objections but in and of itself shouldn't be causing persistence problems.