I am trying to populate the list of an <h:selectOneMenu>. However, the list that I am trying to retrieve is part of another class that is a variable in the base class.
Here is what I have and I'm not sure if this is even possible or how to do it.
I have a Citation class with the following:
public class Citation {
private int id;
private String title;
private Status status;
// getters and setters
}
Then I have a Status class with the following:
public class Status {
private int id;
private String name;
public List<Status> getAll() {
// goes to the database and gets a list of status objects
System.out.println("I was called!");
}
// getters and setters
}
Then on my xhtml page, I have the following:
<h:selectOneMenu id="citation_status" value="#{citation.status}">
<f:selectItems value="#{citation.status.all}" var="s"
itemLabel="#{s.name}" itemValue="#{s.id}" />
</h:selectOneMenu>
However, this doesn't seem to be calling the getAll method in the Status class at all. When the page finishes loading, the select box is empty and the console does not have the output of I was called! from the getAll() method.
I'm a bit new to JSF and I've tried searching the best that I can, but I'm not really sure the terminology to use when searching for this because it's not technically called a "subclass", but that's the best name I can come up with, so needless to say, I've come up with nothing from searching.
Additional Information
If it helps:
I'm using Glassfish as my application server
I'm using Hibernate for my ORM
I'm using JSF 2.0
Apparently #{citation.status} returned null.
That said, this isn't going to work. The h:selectOneMenu value must match the same type as f:selectItem itemValue which is in this case an int. You would get a converter exception.
How to solve this the best depends on the functional requirement which is yet unclear in the question. Maybe you need f:selectItem itemValue="#{s}", or you need h:selectOneMenu value="#{citation.id}".
Update: as to the converter, here's a kickoff example:
#FacesConverter(forClass=Status.class)
public class URLConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
try {
return someStatusDAO.findById(Long.valueOf(value));
} catch (SomeException e) {
throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Status", value)), e);
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return String.valueOf(((Status) value).getId());
}
}
You need a public getter for status in Citation.
Related
I have simple document class:
public class Player {
private String name;
private String age;
}
I want to extend it with field Parameters:
public class Player {
private String name;
private String age;
private Parameters parameters;
public class Parameters {
boolean leftFooted;
boolean leftHanded;
}
}
My Mongock #Execution method would be:
#Execution
public void execution(PlayerRepository playerRepository) {
playerRepository.findAll()
.stream()
.map(this::setDefaultParameters)
.forEach(playerRepository::save);
}
with method:
private Player setDefaultParameters(Player player) {
if (player.getParameters == null) {
player.setParameters(new Parameters(false, false));
}
return player;
}
My question is - how to implement #RollbackExecution method if documents created after model extension can also have Parameters field with values 'false, false' and I just can not set Parameters field to null for all documents in database?
First, am I right on the assumption that, before executing the #Execution method, there may be some documents which already have the parameters field with some value? And, after the execution, you struggle to identify those ones amended in the actual change unit versus those that already had the parameters field?
If that’s the case, you really are not breaking anything, and you would leave the #RollbackExecution empty, and the updated documents will remain with its default value in parameters field.
If you still care, you need to somehow mark those documents that you updated in the ChangeUnit (with a flag or something), so you can filter by the flag and restore your changes.
I've saw a video where is possible to set named locators for allure report
to get view $(locatorname).click - passed:
There is code:
public class Named extends NamedBy {
private final By origin;
private String name;
public Named(By origin) {
this.origin = origin;
}
public Named as(String name) {
this.name = name;
}
#Override
public String toString() {
return Objects.nonNull(name) ? name : this.origin.toString();
}
#Override
public List<WebElement> findElements(SearchContext context) {
return new Named(By.id(id));
}
}
And code for elements:
SelenideElement button = $(id("someid").**as("locatorName")**)
and then should be possible to work with this element.
But i can't.
I dont have method as when i try to create selenideElement.
Pls help. such report is mush more readble.
video URL: https://youtu.be/d5gjK6hZHE4?t=1300
Your example doesn't seem to be valid. At least, a method as must return this. Moreover, id in the overridden findElements is missing. Plus, it's not really clear why you extend NamedBy instead of By.
Anyway, that's just a wrapper around By. To see those locators' names in report you have to follow a previous example in a video first (event listener), before completing NamedBy implementation.
P.S. To make it works the same way as was introduced in the code snippet, you have to add an additional creational logic, e.g.:
public static NamedBy id(String locator) {
return new NamedBy(By.id(locator));
}
I have a bean which has lot of property and half of them n to n relationship. I have also added additional transient 'isEdited' boolean to make sure user has done some changes so I can reduce db fetch for all entities. My current problem sometimes I need to serialize my bean and want to compare properties with real instance. First solution I have tried is from apache commons-lang => EqualsBuilder.reflectEqual(); method which doesnt works well for me because some of inherited items doesn`t implements equals method in right way and I can not edit them. I know I can add ajax listeners to update edited property or I can update each setter method or a new equals implementation. But I am looking for little bit more practical and generic way so I can use this implementation also in the future as well.
So what I want:( Lets say I have a simple bean):
public class Foo {
private String prop1;
private String prop2;
/**
* #return the prop1
*/
public String getProp1() {
return prop1;
}
/**
* #param prop1 the prop1 to set
*/
public void setProp1(String prop1) {
this.prop1 = prop1;
}
/**
* #return the prop2
*/
public String getProp2() {
return prop2;
}
/**
* #param prop2 the prop2 to set
*/
public void setProp2(String prop2) {
this.prop2 = prop2;
}
}
Than my bean will implement an EventListener interface and this listener will handle all setters. In case of any setter method called (after initialization) then edited property will set to true.
So my question is what would be proper way to add action/event listener to handle setters?
EDIT** I have tried PropertyChangeListener but didnt get any event output. And if I add each setters pcs.firePropertyChange(); method then it doesnt make sense that I can set isEdited straight true via those methods.
Can't you have a Map<String,Boolean> and update it with each setter? Take prop1, for example:
public void setProp1(String prop1) {
if(!prop1.equals(this.prop1))
updateMap.put("prop1", true);
this.prop1 = prop1;
}
This way, while saving the entity you'll have a map with that "metadata".
EDIT: There's a flaw tough, because if an user sets a value and then goes back to the original the map will stay in true. You can avoid that by having another map (or cloning your object) with the original values to comparate both things:
public void setProp1(String prop1) {
if(!prop1.equals(this.prop1) && !prop1.equals(ORIGINAL_VALUE))
updateMap.put("prop1", true);
else
updateMap.put("prop1", false);
this.prop1 = prop1;
}
EDIT: Adam is right about aspects and indeed it's a change that can cost you some time. Also, if you want to use reflection there's another catch because you're tied to the structure of the methods. In the future if you want to change a method's name or type you'll have to update that reflection-helper class too.
I'd suggest updating temporal values before saving them so you can compare them to the originals but that would involve changing your methods if you access the fields/object directly without a getter.
In the end, a third option (there's always a third) and the one I think you might be willing to do is using valueChangeListener's in your components. For example:
<h:inputText id="prop1Input" value="#{bean.prop1}" valueChangeListener="#{bean.changesListener}"/>
And your bean should have a method with this structure:
public void changesListener(ValueChangeEvent e) {
//Get the new value
Object o = e.getNewValue();
//get the component's id
String componentId = e.getComponent().getId();
//Cast the value and compare it, after that you should update a map. You are
//going to need one anyway to know which field changed.
boolean valueChanged = //compare against original value
if(componentId.equals("prop1Input"));
map.put("prop1", valueChanged);
}
An important note about this approach, the listener will be executed during the validation phasethe. The intention of this listener is to be able to handle both new and old value, which seems to be your case. Since you can also know the component that fired it you should be fine.
I am developing a JAX-RS webservice using RestEasy 2.2.2 to be deployed to Tomcat 7. The service returns (should return) XML through the use of JAXB. Returned XML should contain representations of ConcurrentHashMap similar to how it is used in the following code:
#XmlRootElement(name="items")
#XmlAccessorType(XmlAccessType.NONE)
public class ItemCollection
{
#XmlElement(name="item")
private ConcurrentHashMap<String, Item> items;
public ItemCollection()
{
items = new ConcurrentHashMap<String, item>();
// fill the map
}
}
The Item class also contains a ConcurrentHashMap that needs to be serialized to XML.
This is the resource class:
#Path("/items")
public class ItemResource
{
#GET
#Produces(MediaType.APPLICATION_XML)
public ItemCollection getAllItems()
{
// get itemManager
return itemManager.getItems(); // ItemManager holds an instance of ItemCollection
}
}
This code runs, but produces an XML with no content:
<items>
<item/>
</items>
What I am trying to get as an output is something like:
<items>
<item id="...">
<data>...</data>
<otheritems>
<otheritem id="...">
<someotherdata>...</someotherdata>
</otheritem>
</otheritems>
</item>
<item id="...">
<data>...</data>
<otheritems>
<otheritem id="...">
<someotherdata>...</someotherdata>
</otheritem>
<otheritem id="...">
<someotherdata>...</someotherdata>
</otheritem>
<otheritem id="...">
<someotherdata>...</someotherdata>
</otheritem>
</otheritems>
</item>
</items>
I found out that a MessageBodyWriter implementation is required where builtin functionality is not sufficient. I tried to come up with a MessageBodyWriter implementation to marshal the ConcurrentHashMap, but I have not been able to get it working so far (i.e. I can get the code being called, but it stops with various exceptions).
It seems I do not quite grasp how MessageBodyWriter (and MessageBodyReader) interfaces should be implemented and used. I have Bill Burke's "RESTful Java with JAX-RS" book. It is very useful in terms of helping design JAX-RS services but I could not find enough details about the MessageBodyWriter functionality in the related section. My internet searches did not yield anything that could guide me in the right direction, either.
I would appreciate if anyone can help me in figuring out how to implement the MessageBodyWriter (and MessageBodyReader) interfaces properly. I do not know if I am missing an annotation, misplacing one or whether I need a completely new approach.
Thanks in advance for helping.
EDIT:
Modifying the code to following gets me halfway there:
#XmlRootElement(name="items")
#XmlAccessorType(XmlAccessType.NONE)
public class ItemCollection
{
private ConcurrentHashMap<String, Item> items;
public ItemCollection()
{
items = new ConcurrentHashMap<String, item>();
// fill the map
}
#XmlElement(name="item")
public Collection<Item> getItems()
{
return items.values();
}
}
This generates the XML that I need (sample included above). However, this code does not work when it comes to unmarshalling. I get the following exception:
java.lang.UnsupportedOperationException
java.util.AbstractCollection.add(AbstractCollection.java:221)
com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.addToPack(Lister.java:290)
com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.addToPack(Lister.java:254)
com.sun.xml.internal.bind.v2.runtime.unmarshaller.Scope.add(Scope.java:106)
com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty$ReceiverImpl.receive(ArrayERProperty.java:195)
com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.endElement(UnmarshallingContext.java:507)
com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:145)
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601)
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782)
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2938)
com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:200)
com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173)
javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:142)
javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:151)
javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:169)
// ... the rest
I assume the reason is the lack of a "proper setter" so that the unmarshaller does not try to add items into a Collection but I do not know how that setter would look like. If anyone knows how to do this, I would appreciate the help.
Thanks in advance.
EDIT 2:
BTW, I have seen Chris' reply where he suggests using #XmlJavaTypeAdapter. I have tried the suggestion and it gets me close to the XML I need. However, the XML I get using #XmlJavaTypeAdapter has an extra level in it (<class><items><item> instead of <items><item> --- as seen in my examples, I have the ConcurrentHashMap instances as a member variable of a class). I also can't seem to change the element name of the individual map items (they are always called "item").
These are not big problems and I can make the necessary changes and live with them if necessary. If possible, however, I would like to not have them in the first place. For educational purposes, I would also like to understand why the code in EDIT 1 does not work for unmarshalling (and how to fix it, if possible).
Thanks in advance for all the help.
I think your problem is that you are trying to mix JAXB with your MessageBodyReader/MessageBodyWriter. You have a JAXB object so you do not really want RestEasy to do all of the serialization using your MessageBodyWriter as it would not take into account your JAXB objects. You could do it this way, but you would need to serialize the rest of your object model too.
The MessageBodyReader/Writer is geared for working with Streams which is probably why it did not make much sense. It makes no assumptions that you are going to XML.
What you probably want to do is create an JAXB XmlJavaTypeAdapter for the map and let JAXB do the XML creation. You can find more information on the JavaDoc page:
http://download.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/adapters/XmlJavaTypeAdapter.html
I did find one good post on this over the Metro mailing list here. This code should give you what you want. The context was around JAX-WS but you are looking specifically for the JAXB annotation to do a custom binding.
#XmlRootElement
public class Root
{
private String name;
private int junk;
#XmlJavaTypeAdapter(MapAdapter.class)
private Map<String, Boolean> lights;
public Root()
{
name = ""; junk = 0; lights = new HashMap<String, Boolean>();
}
public void setName(String newName) { name = newName; }
public String getName() { return name; }
public void setJunk(int newJunk) { junk = newJunk; }
public int getJunk() { return junk; }
public void turnLightOn(String lightName) { lights.put(lightName, true); }
public void turnLightOff(String lightName) { lights.put(lightName, false); }
}
class MapAdapter extends XmlAdapter<MapElements[], Map<String, Boolean>>
{
public MapElements[] marshal(Map<String, Boolean> arg0) throws Exception
{
MapElements[] mapElements = new MapElements[arg0.size()];
int i = 0;
for (Map.Entry<String, Boolean> entry : arg0.entrySet())
mapElements[i++] = new MapElements(entry.getKey(), entry.getValue());
return mapElements;
}
public Map<String, Boolean> unmarshal(MapElements[] arg0) throws Exception
{
Map<String,Boolean> r = new HashMap<String,Boolean>();
for(MapElements mapelement : arg0)
r.put(mapelement.key, mapelement.value);
return r;
}
}
class MapElements
{
#XmlElement public String key;
#XmlElement public Boolean value;
private MapElements() {} //Required by JAXB
public MapElements(String key, Boolean value)
{
this.key = key;
this.value = value;
}
}
The XmlJavaTypeAdapter method works OK in that it allows JAXB do the serialization and back. However, it does not give me the XML that I need. I thought that would not matter too much, but at the end it turned out that I need to get the XML in that form.
The XML I get using #XmlJavaTypeAdapter has an extra level in it (similar to <collection><mapitem><item><mapitem><item> instead of <collection><item><item>). I found a post on a forum (I will add the link if I can find it again) that explains this issue and indicates that in order to get this type of XML, JAXB needs to see a collection, rather than a map.
So, with the hope that it will be useful to others, here's what I did:
First, I defined this interface:
public interface MyCollectionInterface
{
public String getItemId();
}
Then I modified the items to be put in the collection as follows:
public class CollectionItem implements MyCollectionInterface
{
#XmlAttribute
private String id; // This was already a class member
#Override
public String getItemId()
{
return id;
}
}
The idea is to have a known way to get the key to be used with the HashMap.
Then came the declaration for MyCollection
public class MyCollection<E extends MyCollectionInterface> extends AbstractSet<E>
{
private ConcurrentHashMap<String, E> items;
public MyCollection()
{
items = new ConcurrentHashMap<String, E>();
}
#Override
public boolean add(E e)
{
return items.putIfAbsent(e.getItemId(), e) != null;
}
#Override
public Iterator<E> iterator()
{
return items.values().iterator();
}
#Override
public int size()
{
return items.size();
}
// other functionality as needed
}
Now, modifying the code to the following form puts everything into place:
#XmlRootElement(name="items")
#XmlAccessorType(XmlAccessType.NONE)
public class ItemCollection
{
#XmlElement(name="item")
private MyDictionary<CollectionItem> items;
public ItemCollection()
{
items = new MyDictionary<CollectionItem>();
}
}
This produces the XML I was after (see my original post for an example).
Where should I locate the code for validating an employee ID (badge) that will be entered in multiple html forms through out my application?
Currently I have it in the STKUserForm.java which is used when people login (authenticateUser) or request their password (requestPassword). This works great so far. I have to send my many thanks to BalusC. A lot of what I have working so far is based on his DAO/Servlets blog. Thanks BalusC!!!!!!!!!!
But now, I am creating another use case besides logging in, where a supervisor assigns a task (CommitmentItemForm.java) to an employee by entering the employee's badge. I'd rather not duplicate my business logic (someday a valid badge may have 7 digits)there so I feel I need to move it out of STKUserForm.
STKUserForm.java - called from the login page (by a servlet) and both methods mentioned above call the processBadge which then calls the validateBadge method.
public final class STKUserForm extends Form {
public STKUser authenticateUser(STKUser LoginUser) {
<snip>
processBadge(LoginUser.getBadge());
<snip>
return authenticatedUser;
}
public void requestPassword(STKUser loginUser) {
<snip>
processBadge(LoginUser.getBadge());
<snip>
}
public void processBadge(String badge) throws DAOException {
try {
validateBadge(badge);
} catch (ValidatorException e) {
setError(FIELD_USERBADGE, e.getMessage());
}
}
public void validateBadge(String badge) throws ValidatorException, DAOException {
if (badge != null) {
if (!FormUtil.isBadge(badge)) {
throw new ValidatorException("Please enter valid badge (6 digits, numbers only, and no 'E').");
} else if (!STKUserDAO.isValidEmployee(badge)) {
throw new ValidatorException("This is not a valid badge of any EB Employee.");
}
}
}
}
So where should I move the validateBadge method?? STKUser bean?? FormUtil??? Some other utility class??? I'm unsure because it makes a call to STKUserDAO. I'll want to validate an employee badge for many use cases through out this and other applications.
I would have the STKUserDAO.isValidEmployee() provide all the functionality of the STKUserForm.validateBadge() method, throw the exceptions inside STKUserDAO.isValidEmployee() instead. Then your validation is available where ever you are accessing the DB.
One solution is to make the bade id a domain value object:
public final class BadgeId {
private final String value;
public BadgeId(String value) {
if(value not valid badge id) throw IllegalArgumentException("invalid: " + value);
this.value = value;
}
public String getValue() {
return value;
}
// equals and hashcode
}
Now you can use BadgeId instead of String in all of your methods. The Action form can have a getBadgeId() : BadgeId method for convenience. Since BadgeId is immutable and the constructor enforces validity, you don't ever have to worry about invalid BadgeId objects flying around.
If this sounds crazy, think about JDK classes such as Integer, Float, etc. They didn't have to exist. We could just pass String objects around and call Float.validate(String) and Float.isValid(String) etc. Instead, domain objects for building programming (Float, Double, etc.) were created.
Another useful method for the BadgeId class might be:
public static BadgeId toBadgeId(String value) { ... }
If you expect to have many types of BadgeId objects, all with different validation rules, you could use something like:
public abstract class BadgeId {
... same constructs / methods as before except ...
protected abstract boolean isValid(String value);
}
public final class NumericBadgeId extends BadgeId {
public NumericBadgeId(String value) {
super(value);
}
protected boolean isValid(String value) {
return true if value contains all numbers; false otherwise
}
}