beans properties and modelDriven in struts 2 - struts2

I am new to struts 2. I created an action class that insert data from JSP page to a bean using ModelDriven interface.
The problem is that i have some non 'Stringproperties in the bean likeLong,Date` ... etc
The problem is:
when i press submit button in the jsp page i get an error saying that it did not find the a string setter for that particular property.
for example if i have in my bean
package com.hsms.aseza.enteringApproval
Class EnteringApproval
private Date approvalDate
Date getApprovalDate()
{
return employeeId;
}
void setApprovalDate(Date employeeId)
{
this.employeeId = employeeId;
}
when the action class that implement the model driven is executed, it fires a run time exception
java.lang.NoSuchMethodException: com.hsms.aseza.enteringApproval.EnteringApproval.setApprovalDate([Ljava.lang.String;)
Is there anyway to solve this problem without writing a String setter for my Date property?

I think that your problem is conversion i.e. conversion from String to your java.util.Date Object. This class extends this which is responsible for converting from String to other types like Long, Double etc. If you check the source code for DefaultTypeConverter, you won't see any conversion for either java.util.Date or java.sql.Date. So i think what you should do is to write a converter for approvalDate. My previous post on this will guide you on the procedure, all you will need is to edit the code to suit your needs.
On your jsp, follow this datepicker example
Use the same format i.e date format used to display your date in your jsp with SimpleDateFormat to do your conversion in convertFromString method of your converter and return the converted java.util.Date or java.sql.Date.
Let me know if you have issues implementing this.

Try use the s:date tag in your jsp.
Edit:
Try use:
<s:textfield key="objEnteringApproval.approvalDate"></s:textfield>
in which objEnteringApproval is your public accessible variable in your controller.

Make sure you have initialized your bean in your action class
Private YourBean bean = new YourBean();
Or you can have it in the constructor
Make sure your getter and setter are public
If you are trying to type date on the jsp page, please use datepicker e.g. sx:datetimepicker or sj:datepicker

Related

Spring Data Rest Binding

I am trying to work with Spring-Data-Rest, but I am hanging that Spring is not binding my body object given via Post.
My domain class looks like:
#Entity
#EqualsAndHashCode
#ToString
public class Rendite{
#Id #GeneratedValue Long id;
double jahresNettoMiete;
public Rendite(){}
}
#RepositoryRestResource(collectionResourceRel = "renditen", path = "renditen")
public interface RenditeRepositoryextends CrudRepository<Rendite, Long> {}
Calling the via Get works fine:
Calling the POST to save an entity calls the Application, too, but it doesnt bind the value to the property:
You appear to be missing getters (and optionally) setters on your entity.
Adding a public getter for the relevant field(s) should allow for both serlialization and deserialization.
See further on this here:
http://www.baeldung.com/jackson-field-serializable-deserializable-or-not
Unintuitively, the getter also makes the private field deserializable
as well – because once it has a getter, the field is considered a
property.
You can control serialization/deserialization in various ways as outlined in the article.
Another approach rather than adding getters would be to use:
#JsonAutoDetect(fieldVisibility = Visibility.ANY)
as outlined in example 4.5 at the below:
http://www.baeldung.com/jackson-annotations

#FacesConverter without converter-id and forClass

What should work properly if I do not specify the converter-id and(or) forClass in determining the #FacesConverter annotation?
For example:
#FacesConverter
public class SplitConverter implements Converter{
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
//...
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
//...
}
After registred in faces-config.xml and use that on .xhtml page:
<h:inputText id="badges" value="#{article.badges}"
required="true">
<f:converter converterId="com.katcgr.SplitConverter" />
</h:inputText>
And all is work. The documentation say that
if converter-id is the empty string, Application.addConverter(java.lang.Class,java.lang.String) is called, passing the converter-for-class as the first argument and the derived converter-class as the second argument.
But why everything works fine even if I not specified the forClass ?
After registred in faces-config.xml
Registration via #FacesConverter and <converter> in faces-config.xml are mutually exclusive whereby the XML registration overrides any annotation registration. So, when your converter is referenced via the converter ID as registered in XML, then the converter instance behaves basically exactly as if it had no annotations. If you remove the XML registration, then you should have retrieved the below exception on specified converterId:
javax.faces.FacesException: Expression Error: Named Object: com.katcgr.SplitConverter not found.
at com.sun.faces.application.ApplicationImpl.createConverter(ApplicationImpl.java:1339)
at javax.faces.application.ApplicationWrapper.createConverter(ApplicationWrapper.java:393)
at com.sun.faces.facelets.tag.jsf.ConverterTagHandlerDelegateImpl.createConverter(ConverterTagHandlerDelegateImpl.java:158)
...
This would basically only work if you had a
#FacesConverter("com.katcgr.SplitConverter")
If you however remove both the XML configuration and the <f:converter>, then it will "work" because the #FacesConverter without an explicit forClass will be automatically invoked for every bean property which is an instance of java.lang.Object (basically, everything), which does not have a more specific converter already registered. In other words, your converter will behave like:
#FacesConverter(forClass=Object.class)
It hopefully doesn't need an elaborate explanation that this is a terribly bad idea. It will also confuse PrimeFaces, because it will then internally initialize and use it as default converter for String class.

Which one takes higher precendence between value and forClass in FacesConverter annotation when defining custom converter?

I have the following as annotation for the custom converter
#FacesConverter(value="capsConverter", forClass=String.class)
public class CapsConverter implements Converter{
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return value.toUpperCase();
}
#Override
public String getAsString(FacesContext context, UIComponent component,Object value) {
if(value!=null && value instanceof String){
String s = (String)value;
s = WordUtils.capitalize(s.toLowerCase());
return s;
}
return null;
}
}
Issue is, the converter sometimes gets called even when I didnt explicitly call it in my page, does the forClass have anything to do with the interference for my inputTexts, should I be using value only and remove forClass=String.class ?
Any shed of light is highly appreciated.
It are actually two distinct ways of registering a converter. Both are mutually exclusive. They have no influence on each other and you can omit one or the other.
The forClass attribute will register the converter in the JSF application to kick in during processing and rendering of every model value of the specified type. In other words, with forClass=String.class, the converter will be implicitly invoked for every String typed input and output, unless the associated input/output component has already an explicit converter declared.
Generally you use forClass only for custom/complex types, not for standard types such as String, Long, BigDecimal, etc for which JSF has already builtin implicit converters.
So you should indeed remove it and rely on converter ID only.
#FacesConverter("capsConverter")
<h:someComponent ... converter="capsConverter" />
An example of correct appliance of forClass would be the following converter between a Person entity and a String representing its ID
#FacesConverter(forClass=Person.class)
on something like
<f:viewParam name="id" value="#{bean.person}" />
which converts an incoming request parameter representing an entity ID like below
/edit-person.xhtml?id=42
to a fullworthy entity property in bean (without needing any additional logic in bean)
private Person person;

spring MVC model attributes in jsp page

When I access simple model data like the username using : ${username} everything seems to be fine. But when I try to use ${userdata.uname} I get an error like :
Could not find property uname in class com.mydom.datahandling.userdata
userdata is java class I add to the ModelAndView
ModelAndView mav = new ModelAndView("page37");
mav.addObject("sessionID",ID);
mav.addObject("userdata",p37userdata);
What do I need to do differently ? This seems to be happening whenever I try to use something other than a primitive type or String. I obviously need a bit more education. Do I need to serialize p37userdata?
userdata is
public class userdata{
public String uname;
public String otherstuff;
}
The objects you reference from your EL in your JSP should be java beans (or a map). According to wikipedia (the source of all truth) A bean has the following properties:
They are serializable, have a 0-argument constructor, and allow access
to properties using getter and setter methods.
So you should probably add getters and setters to your userdata class.

Use ManagedBean in FacesConverter

I want to use ManagedBean in my Converter. The ManagedBean is responsible for getting data from database. In Converter I want to convert string into object which must be get from database.
This is my Converter
#FacesConverter(forClass=Gallery.class, value="galleryConverter")
public class GalleryConverter implements Converter {
// of course this one is null
#ManagedProperty(value="#{galleryContainer}")
private GalleryContainer galleryContainer;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String galleryId) {
return galleryContainer.findGallery(galleryId);
...
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object gallery) {
...
}
}
I know that galleryContainer will be null and if I want to inject ManagedBean into Converter I can mark it as ManagedBean too. The problem is that I want to do it in beautiful way, I don't want to look for some 'strange solution'. Maybe the problem is in my application? Maybe there is some other good solution to create object which must get data from database and used in converter? I want also to mention that I will prefer to use DependencyInjection instead of creating new object using new statement (it is easier to test and maintain). Any suggestions?
Instead of using #FacesConverter you should use #ManagedBean, because currently faces converter isn't a valid injection target. Nonetheless, you can choose your converter to be a managed bean, thus refer to it in your view as converter="#{yourConverter}" (by managed bean name) instead of converter="yourConverter" (by converter id).
Basic usage example:
#ManagedBean
#RequestScoped
public class YourConverter implements Converter {
#ManagedProperty...
...
//implementation of converter methods
}
Of course, reading BalusC's invaluable Communication in JSF 2.0 will shed some light on this question as well.
It is also worth mentioning that the scope of your converter bean may be changed to, for example, application or session, if it is not supposed to hold any state.

Resources