I have a little issue with a JSF ViewHandlerWrapper that I've coded. It works fine most of the times, but at times I will get a NullPointerException from the very core of Mojarra and thus started to wonder whether I implemented my ViewHandlerWrapper correctly.
public class TokenViewHandler extends ViewHandlerWrapper {
private ViewHandler parent;
public TokenViewHandler(ViewHandler parent) {
this.parent = parent;
}
#Override
public ViewHandler getWrapped() {
return parent;
}
#Override
public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException {
final String token = UUID.randomUUID().toString();
findAndModifyForms(viewToRender, token, context);
getWrapped().renderView(context, viewToRender);
}
private void findAndModifyForms(final UIComponent component, final String token, final FacesContext ctx) {
if (component instanceof UIForm) {
final HtmlInputHidden hidden = (HtmlInputHidden) ctx.getApplication().createComponent(HtmlInputHidden.COMPONENT_TYPE);
hidden.setValue(token);
component.getChildren().add(hidden);
} else {
for (UIComponent tempComponent : component.getChildren()) {
findAndModifyForms(tempComponent, token, ctx);
}
}
}
}
From the code you quickly realize that I want to add a inputHidden-component with a UUID value to each form on the view.
As I haven't found any good examples for ViewHandlerWrappers I assumed that it should look like a ExceptionHandlerWrapper but since I get the occassional NPE using my ViewHandler, I assume that something is wrong and I can't seem to see it.
This seems to be related to a bug in partial state saving, see issue 1414.
The IceFaces guys encountered a similar problem and they got it (temporarily) fixed by adding the following line:
facesContext.getViewRoot().addComponentResource(facesContext, new UIOutput(), "head");
Give it a try. Do it before rendering the view.
Related
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 two ways of saving data in my application: save to database and save to file. Since I don't want client code dealing with construction of objects I created a class that (to my understanding) is simple factory with a factory method. Code below:
public static DataPersister createDataPersister(Boolean saveToDb, Session session, String filename) {
if (saveToDb) {
return new DatabaseDataPersister(session);
} else {
return new FileDataPersister(filename);
}
}
With this setup client code doesn't have to deal with constructing anything or deciding whether to save to DB or file - it can just call a save() method on an object returned by the factory like so:
DataPersister dataPersister = DataPersisterSimpleFactory.createDataPersister(this.savetoDb, this.session, this.filename);
dataPersister.save(this.data);
My question is - is this solution breaking SOLID principles? In order to create e.g. a DatabaseDataPersister client code needs to pass on a filename parameter, and this implementation of DataPersister won't have any use of it. I feel like it doesn't sit right with something similar to Interface-segregation principle but not quite that.
And if the solution is indeed a code smell - how do I go about cleaning it?
The SOLID principle I think is in violation is DIP.
Your client classes, by having to depend on the static factory directly, have a compile-time dependency on actual implementations, DatabaseDataPersister and FileDataPersister, rather than just the abstraction DataPersister.
To solve, supply to the client the DataPersister you want them to use. The constructor is usually a good place for this:
public class ExampleClient {
private final DataPersister dataPersister;
public ExampleClient(DataPersister dataPersister) {
this.dataPersister = dataPersister;
}
public void methodThatUsesSave(){
dataPersister.save(data);
}
}
This code compiles without the concrete implementations, i.e. it has no dependency on them. The client also doesn't need to know the filename or session so it solves that code smell too.
We can decide which concrete implementation to give it at construction time, here I use your existing method:
DataPersister dataPersister = DataPersisterSimpleFactory.createDataPersister(this.savetoDb, this.session, this.filename);
ExampleClient example = new ExampleClient(dataPersister);
This is a perfect opportunity to use the factory pattern
interface DataPersister {
void persist(String s);
}
private class DatabasePersister implements DataPersister {
final Session session;
public DatabasePersister(Session session) {
this.session = session;
}
#Override
public void persist(String s) {
System.out.println("Persist to database: " + s);
}
}
private class FilePersister implements DataPersister {
final String filename;
public FilePersister(String filename) {
this.filename = filename;
}
#Override
public void persist(String s) {
System.out.println("Persist to file: " + s);
}
}
class PersisterFactory {
public DataPersister createDatabasePersister(Session session) {
return new DatabasePersister(session);
}
public DataPersister createFilePersister(String filename) {
return new FilePersister(filename);
}
}
public void test(String[] args) {
DataPersister databasePersister = new PersisterFactory().createDatabasePersister(new Session());
databasePersister.persist("Hello");
DataPersister filePersister = new PersisterFactory().createFilePersister("Hello");
filePersister.persist("Hello");
}
You already pass a bunch of stuff irrelevant to various persisters.
As it stands you need a method that takes a Session and one that takes a String and you're done. No need for a boolean, no need for useless params. That handles your decision making with no cruft.
Whether or not that's a good idea... I'm ambivalent. You're not saving much; might as well just have a static factory in each type so it's explicit in the code what type you're creating.
Consider what happens when you add a new persister, like a REST endpoint, that would take a URL (could be a string, could be an actual URL). You now need even more useless parameters etc. Or you could pass in a URI from the beginning, e.g., file:// or http:// and get around that problem.
There are any number of ways this could be done–I'm not convinced there's a "clearly correct" answer, and it may boil down to opinion.
Well the right solution here is combining the dependency injection from weston and the factory pattern from OldCurmudgeon.
public class ExampleClient {
private final DataPersister dataPersister;
public ExampleClient(DataPersister dataPersister) {
this.dataPersister = dataPersister;
}
public void methodThatUsesSave(){
dataPersister.save(data);
}
}
class PersisterFactory {
public DataPersister createDatabasePersister(Session session) {
return new DatabasePersister(session);
}
public DataPersister createFilePersister(String filename) {
return new FilePersister(filename);
}
}
The upper level code:
PersisterFactory = new PersisterFactory();
DataPersister dataPersister;
if (saveToDb)
dataPersister = PersisterFactory.createDatabasePersister(new Session());
else
dataPersister = PersisterFactory.createFilePersister("Hello");
ExampleClient example = new ExampleClient(dataPersister);
Usually the dataPersister comes from the DI container and the saveToDb comes from the config, but of course testing can be an exception.
I need to use #SessionScope to make a list stay in the page after refreshing, but when I use it, Stripes:error is not diplaying any more. Stripes:error runs actually(as I see nothing will happen) but it just doesn't show the error message in the page any more. I'm sure there is something with #SessionScope because when I run the code without it all the errors shown in the page.
Any Idea of how to fix this?
Note: I also tried to use #Wizard(startEvents="event") and it lets errors to be shown but doesn't do anything with saving the list in the page!
java
#SessionScope
#UrlBinding("/Student/import.action")
public class ImportAction implements ActionBean {
private String userCheckBox;
public Resolution importStudents() throws IOException {
if (userCheckBox == null) {
this.getContext().getValidationErrors().add("userCheckBox",new SimpleError(error));
}
return new RedirectResolution("import.action");
}
public String getUserCheckBox() {
return userCheckBox;
}
public void setUserCheckBox(String userCheckBox) {
this.userCheckBox = userCheckBox;
}
}
jsp
<stripes:checkbox name="userCheckBox"/>
<stripes:errors field="userCheckBox"/>
<stripes:submit name="importStudents" value="Import"/>
I don't know if this is the correct way to do this but instead of using #SessionScope how about storing the list in the session directly via your subclassed ActionBeanContext? For example, mine has
public class IlmpActionBeanContext extends ActionBeanContext {
private static final String REQUEST_TOKEN = "request_token";
public Token getRequestToken() {
return (Token) this.getRequest().getSession()
.getAttribute(IlmpActionBeanContext.REQUEST_TOKEN);
}
public void setRequestToken(final Token requestToken) {
this.getRequest()
.getSession()
.setAttribute(IlmpActionBeanContext.REQUEST_TOKEN, requestToken);
}
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.
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
}
}