After checking out the k-market sample from balana (http://svn.wso2.org/repos/wso2/trunk/commons/balana/modules/balana-samples/kmarket-trading-sample/) i wanted to create a similar sample project. I have created the following 2 classes. The balana source was downloaded from the same trunk.
public class Test {
public static void main(String[] args) throws JDOMException, IOException, SAXException, URISyntaxException {
//Create the xacml request as a string
Document xacmlRequest = createXACMLRequest();
String requestString = writeRequestToString(xacmlRequest);
//Specify XACML Policies Directory
//System.setProperty(ConfigurationStore.PDP_CONFIG_PROPERTY, "Config/config.xml");
System.setProperty(FileBasedPolicyFinderModule.POLICY_DIR_PROPERTY, "Policies");
Balana balana = Balana.getInstance();
PDPConfig pdpConfig = balana.getPdpConfig();
//Keep ONLY my SampleAttributeFinderModule for testing purposes
AttributeFinder attributeFinder = pdpConfig.getAttributeFinder();
//List<AttributeFinderModule> modules = attributeFinder.getModules();
List<AttributeFinderModule> modules = new ArrayList<AttributeFinderModule>();
modules.add(new SampleAttributeFinderModule());
attributeFinder.setModules(modules);
PDPConfig newPDPConfig = new PDPConfig(attributeFinder, pdpConfig.getPolicyFinder(), pdpConfig.getResourceFinder(), false);
PDP pdp = new PDP(newPDPConfig);
System.out.println(pdp.evaluate(requestString));
}
and
public class SampleAttributeFinderModule extends AttributeFinderModule {
#Override
public boolean isDesignatorSupported() {
return true;
}
#Override
public Set<String> getSupportedCategories() {
Set<String> categories = new HashSet<String>();
categories.add("urn:oasis:names:tc:xacml:3.0:attribute-category:resource");
return categories;
}
#Override
public Set getSupportedIds() {
Set<String> ids = new HashSet<String>();
ids.add("http://wso2.org/claims/emailaddress");
return ids;
}
#Override
public EvaluationResult findAttribute(URI attributeType, URI attributeId, String issuer,
URI category, EvaluationCtx context) {
System.out.println("Custom Attribute Finder initiated");
List<AttributeValue> attributeValues = new ArrayList<AttributeValue>();
//Just return the same value, for test purposes
attributeValues.add(new StringAttribute("Tom"));
return new EvaluationResult(new BagAttribute(attributeType, attributeValues));
}
While i think the above code should work , my SampleAttributeFinderModule is never called, and the evaluation only succeeds if my request contains the specified attribute. My Policy is this :
<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17 http://docs.oasis-open.org/xacml/3.0/xacml-core-v3-schema-wd-17.xsd"
Version="1.0"
PolicyId="SamplePolicy"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:permit-overrides">
<Target/>
<!-- Rule to see if we should allow the Subject to login -->
<Rule RuleId="LoginRule" Effect="Permit">
<Target/>
<Condition>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-one-and-only">
<AttributeDesignator
AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id"
Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="true"/>
</Apply>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-one-and-only">
<AttributeDesignator
AttributeId="http://wso2.org/claims/emailaddress"
Category="urn:oasis:names:tc:xacml:1.0:subject-category:resource"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="true"/>
</Apply>
</Apply>
</Condition>
</Rule>
<!-- We could include other Rules for different actions here -->
<!-- A final, "fall-through" Rule that always Denies -->
<Rule RuleId="FinalRule" Effect="Deny"/>
</Policy>
Any help would be appreciated. Note that, after looking at the balana source , and after tracking how it's methods are called, i stumbled upon the following piece of code (im sure this is called when i run the program). It seems like it first tries to get the attributes from the request, but the first if always evaluates to false if the attributeis not in the request (i think), so the callHelper method which contains the modules is never called. Is this intended?
package org.wso2.balana.ctx.xacml3;
public class XACML3EvaluationCtx extends BasicEvaluationCtx {
// other methods
public EvaluationResult getAttribute(URI type, URI id, String issuer, URI category) {
List<AttributeValue> attributeValues = new ArrayList<AttributeValue>();
Set<Attributes> attributesSet = mapAttributes.get(category.toString());
if(attributesSet != null && attributesSet.size() > 0){
Set<Attribute> attributeSet = attributesSet.iterator().next().getAttributes();
for(Attribute attribute : attributeSet) {
if(attribute.getId().equals(id) && attribute.getType().equals(type)
&& (issuer == null || issuer.equals(attribute.getIssuer()))
&& attribute.getValue() != null){
List<AttributeValue> attributeValueList = attribute.getValues();
for (AttributeValue attributeVal : attributeValueList) {
attributeValues.add(attributeVal);
}
}
}
if(attributeValues.size() < 1){
return callHelper(type, id, issuer, category);
}
}
//If i put this piece of code here instead of up there (outside the first if) , it works as i want to
/*if(attributeValues.size() < 1){
return callHelper(type, id, issuer, category);
}*/
// if we got here, then we found at least one useful AttributeValue
return new EvaluationResult(new BagAttribute(type, attributeValues));
}
Related
I need to make a program that takes an .xml file that uses the SAX Parser in Java to parse the .xml file, store it in an arrayList and then call methods to display certain objects with the arrayList.
My program needs to be able to handle the user giving the SAX Parser bad data such that if it doesn’t have a certain tag it’s looking for, then it won’t break. I need it to be able to load the data and use a “check” command to check the intergrity of the data. For example, if the customer doest’t have an account associated with it, the program will output which customer doesn’t have an account.
Below, I’ve put the task for the program, the Handler, and the .xml with bad data below.
Task for the program:
check : This command is used to check the integrity of the named entries. In other words, it checks to see that all the entries of a given type are correct. For example, if the command is:
check customer
the program should list all customers (first name and last name) that do not have any accounts. Related commands include:
check account : list any account number without an associated address
check address : list any address without an associated meter
check meter : list any meter id without any meter readings, or whose readings do not match the meter type, e.g., push reading from a polling meter.
.xml File:
<xml version="1.0" encoding="UTF-8">
<!-- Customer with no account -->
<customer lastName ="Anderson" firstName="Thomas">
</customer>
<!-- Account with no address -->
<customer lastName ="Baker" firstName="Susanne">
<account type="residential" accountNumber="999-999-99">
</account>
</customer>
<!-- Address with no meter -->
<customer lastName ="Charles" firstName="Henry">
<account type="residential" accountNumber="888-888-88">
<address type="apartment" unit="308" street="E 6th St." number="56" zipCode="13126"/>
</account>
</customer>
<!-- Meter with no readings -->
<customer lastName ="Davidson" firstName="Mary">
<account type="residential" accountNumber="666-666-66">
<address type="apartment" unit="308" street="W 9th St." number="67" zipCode="13126">
<meter id = "RM-4876-X4" brand="GE" type="poll" location = "West side of building"/>
</address>
</account>
</customer>
<!-- Meter with mismatched readings -->
<customer lastName ="Evans" firstName="Oscar">
<account type="residential" accountNumber="555-555-55">
<address type="house" street="E 10th St." number="78" zipCode="13126">
<meter id = "RM-4874-X4" brand="GE" type="poll" location = "North side">
<meterReading reading="650" date = "1413227815" flag="poll"/>
<meterReading reading="675" date = "1413314215" flag="push"/>
<meterReading reading="622" date = "1413400615" flag="poll"/>
</meter>
</address>
</account>
</customer>
</xml>
Handler File:
package csc241hw07;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MyHandler extends DefaultHandler {
// Variables to hold current values
private ArrayList<Customer> customerList = new ArrayList<Customer>();
private Customer currentCustomer;
private Account currentAccount;
private Address currentAddress;
private Meter currentMeter;
//getter method for employee list
public ArrayList<Customer> getCustList() {
return customerList;
}
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if (qName.equalsIgnoreCase("customer")) {
//Create a customer object
String lastName = attributes.getValue("lastName");
String firstName = attributes.getValue("firstName");
currentCustomer = new Customer(lastName, firstName);
} else if (qName.equalsIgnoreCase("address")) {
// Create an Address object
String street = attributes.getValue("street");
int houseNumber = Integer.parseInt(attributes.getValue("number"));
String zipCode = attributes.getValue("zipCode");
String type = attributes.getValue("type");
String unit = attributes.getValue("unit");
if (type.equalsIgnoreCase("mailing")) {
// this is a mailing address -- assign to current customer
MailingAddress ma = new MailingAddress(street, houseNumber, zipCode, type);
currentCustomer.setMailingAddress(ma);
} else if (type.equalsIgnoreCase("house")) {
// Create a house
currentAddress = new House(street, houseNumber, zipCode, type);
} else if (type.equalsIgnoreCase("commercial")) {
// Create a commercial
currentAddress = new Commercial(street, houseNumber, zipCode, type);
} else if (unit != null) {
// Create an apartment
currentAddress = new Apartment(street, houseNumber, zipCode, type, unit);
} else {
System.out.println("Unknown address type:" + type);
}
if (currentAddress != null) {
// Assign this account to current address
currentAddress.setAccount(currentAccount);
currentAccount.addAddress(currentAddress);
}
} else if (qName.equalsIgnoreCase("meter")) {
// Create a meter object
String type = attributes.getValue("type");
String brand = attributes.getValue("brand");
String id = attributes.getValue("id");
if (type.equalsIgnoreCase("push")) {
currentMeter = new PushMeter(id, brand, type);
} else if (type.equalsIgnoreCase("poll")) {
currentMeter = new PollMeter(id, brand, type);
} else {
System.out.println("Unknown meter type: " + type);
}
if (currentMeter != null) {
// Set location
String location = attributes.getValue("location");
currentMeter.setLocation(currentAddress, location);
currentAddress.addMeter(currentMeter);
}
//System.out.println("METER:");
} else if (qName.equalsIgnoreCase("meterReading")) {
// Create a meter reading
//<meterReading reading="622" date = "1413400615" flag="push"/>
double reading = Double.parseDouble(attributes.getValue("reading"));
//System.out.println("DATE:" );
ZoneOffset z = ZoneOffset.ofHours(5);
long epoch = Long.parseLong(attributes.getValue("date"));
LocalDateTime d = LocalDateTime.ofEpochSecond(epoch,0,z);
//System.out.println("DATE:" + d.toString());
String flag = attributes.getValue("flag");
MeterReading mr = new MeterReading(reading, d, flag, currentMeter);
// Add this to current meter
currentMeter.addReading(mr);
//System.out.println("METERREADING:");
} else if (qName.equalsIgnoreCase("account")) {
// <account type="residential" accountNumber="876-543-21">
String type = attributes.getValue("type");
String acctNum = attributes.getValue("accountNumber");
if (type.equalsIgnoreCase("residential")) {
// residential account
currentAccount = new ResidentialAccount(acctNum, currentCustomer);
} else if (type.equalsIgnoreCase("commercial")) {
currentAccount = new CommercialAccount(acctNum, currentCustomer);
} else {
System.out.println("Unknown account type:" + type);
}
if (currentAccount != null) {
// Add this account to current customer
currentCustomer.addAccount(currentAccount);
}
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equalsIgnoreCase("customer")) {
customerList.add(currentCustomer);
currentCustomer = null;
} else if (qName.equalsIgnoreCase("meter")) {
currentMeter = null;
} else if (qName.equalsIgnoreCase("account")) {
currentAccount = null;
} else if (qName.equalsIgnoreCase("address")) {
currentAddress = null;
}
}
}
Thank you!
You can add one more list with "bad" customers like:
// Variables to hold current values
private ArrayList<Customer> customerList = new ArrayList<Customer>();
private ArrayList<Customer> badCustomerList = new ArrayList<Customer>();
...
And add some changes sorting those customers out of "good" ones. For instance:
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equalsIgnoreCase("customer")) {
if (isCustomerGood(currentCustomer)) { // Here is checking code
customerList.add(currentCustomer);
} else {
badCustomerList.add(currentCustomer);
}
currentCustomer = null;
} else if (qName.equalsIgnoreCase("meter")) {
currentMeter = null;
} else if (qName.equalsIgnoreCase("account")) {
currentAccount = null;
} else if (qName.equalsIgnoreCase("address")) {
currentAddress = null;
}
}
private static boolean isCustomerGood(Customer customer) {
return customer.getAccount() != null;
}
public boolean check() {
return badCustomerList.isEmpty();
}
public List<Customer> getBadCustomers() {
return badCustomerList;
}
Actually you can implement isCustomerGood differently depending on your needs. Now you just run check method at the end of parsing.
First of all, by bad data I dont think you mean a non-wellformed XML file that causes parsing exception.
If the above assumption is true, then I think you should consider using XPath to query the data file and check for the condition where the target element does not exist...
So why are you not using XPath which would make your code a lot easier to write and maintain?
I have an HTTP Security API which can be configured for security, authentication and authorization like this
SecurityConfigurationBuilder configurationBuilder = new SecurityConfigurationBuilder();
HttpSecurityBuilder builder = configurationBuilder.http();
builder
.pathGroup("REST Service Group A") //returns PathConfigurationBuilder
.inbound() //returns InboundConfigurationBuilder
.authc() //returns AuthenticationConfigurationBuilder
.form() //returns FormAuthenticationConfigurationBuilder
.loginPage("/loginA.html")
.errorPage("/errorA.html")
.authz()
.allowedRoles("Role A")
.pathGroup("REST Service Group B")
.inbound()
.authc()
.form()
.loginPage("/loginB.html")
.errorPage("/errorB.html")
.authz() //returns AuthorizationConfigurationBuilder
.allowedRoles("Role B")
.path("/rest/a/*", "REST Service Group A") //returns PathConfigurationBuilder
.path("/rest/b/*", "REST Service Group B");
HttpSecurityConfiguration configuration = builder.build().getHttpSecurityConfiguration();
Note: Each config method returns an object of a class. I have mentioned only a few of them.
Similarly, we can also configure in this way,
SecurityConfigurationBuilder configurationBuilder = new SecurityConfigurationBuilder();
HttpSecurityBuilder builder = configurationBuilder.http();
builder
.allPaths()
.inbound()
.authc()
.form()
.loginPage("/login.html")
.errorPage("/error.html")
.authz()
.allowedRoles("Role A", "Role B")
.allowedGroups("Group A", "Group B")
.allowedRealms("Realm A", "Realm B")
.expression("#{identity.isLoggedIn()}");
HttpSecurityConfiguration configuration = builder.build().getHttpSecurityConfiguration();
I am now required to provide similar configuration using annotations on enum fields. For eg.
//Declaration of #annotation_A depends on #annotation_B means that annotation_B can only be declared if annotation_A is declared.
//Also, declaration of annotation_A must precede annotation_B
#PicketlinkHttpSecurity
public interface Security {
static enum Secure {
//optional
#Http
//Any one of these,optional
#Permissive
#Restrictive
//Any one of these, optional
#AllPaths
#Path(pathName = "Path URL Pattern")
#Path(pathName = "Path URL Pattern", pathGroup = "Path Group")
#PathGroup(pathGroup = "Path Group")
//optional, declaration depends on (#allPaths, #path, #pathGroup) whichever is declared
#Logout
//optional, declaration depends on (#allPaths, #path, #pathGroup) whichever is declared
#Inbound
//optional, declarion depends on #inbound
#Methods(methods = {"method_one", "method_two"}, ...)
//optional, declaration depends on #inbound
#Headers(headerName = "name", headerValues={"value1", "value2", ...}, requestedWith = "request_header")
//optional, declaration depends on (#allPaths, #path, #pathGroup) whichever is delclared
#Outbound
//optional, declaration depends on #outbound
#RedirectTo(redirect = "redirectPath")
//optional, declaration depends on #inbound/#outbound
#Authc
//Any one of form,basic,digest,x509,token(//optional and declaration depends on #authc)
#Form(restoreOriginalRequest = "yes_OR_no", loginPage="loginPage", errorPage="errorPage")
#Basic(realmName="realmName")
#Digest(realmName="realmName")
#X509(subjectRegex="")
#Token
//optional, declaration depends on #inbound/#outbound
#Authz
//optional, any one or many of these, declaration depends on #authz
#AllowedRoles(Roles={"Role_A", "Role_B", ...})
#AllowedGroups(Goups={"Goup_A", "Goup_B", ...})
#AllowedRealms(Realms={"Realm_A", "Realm_B", ...})
#Expressions(expressions= {"expression1", "expression2", ...})
SecurityConfigiration_One,
//Other Security Configuration Annotations Decorated Enum Fields
}
}
Now, I have a class SecurityConfigExtension which tries to read this enum class and build up SecurityConfigurationBuilder. An incomplete piece of code from this class is
public class SecurityConfigExtension implements Extension {
private transient final Logger log = Logger.getLogger(SecurityConfigExtension.class);
SecurityConfigurationBuilder builder = new SecurityConfigurationBuilder();
HttpSecurityBuilder httpSecurityBuilder = new HttpSecurityBuilder(builder);
PathConfigurationBuilder pathConfigurationBuilder;
public <T> void processAnnotatedType(#Observes ProcessAnnotatedType<T> event) {
AnnotatedType<T> tp = event.getAnnotatedType();
if (tp.isAnnotationPresent(PicketlinkHttpSecurity.class)) {
if (!tp.getJavaClass().isInterface()) {
log.warn("ViewConfig annotation should only be applied to interfaces, and [" + tp.getJavaClass()
+ "] is not an interface.");
} else {
for (Class<?> clazz : tp.getJavaClass().getClasses()) {
for (Field enumm : clazz.getFields()) {
for (Annotation a : enumm.getAnnotations()) {
if (a.annotationType() == Http.class) {
this.httpSecurityBuilder = this.builder.http();
} else if (a.annotationType() == Permissive.class) {
this.httpSecurityBuilder = this.httpSecurityBuilder.permissive();
} else if (a.annotationType() == Restrictive.class) {
this.httpSecurityBuilder = this.httpSecurityBuilder.restrictive();
} else if (a.annotationType() == AllPaths.class) {
this.pathConfigurationBuilder = this.httpSecurityBuilder.allPaths();
} else if (a.annotationType() == Path.class) {
Path path = (Path) a;
String pathName = path.pathName();
String pathGroup = path.pathGroup();
if (pathName != null && !pathName.isEmpty() && pathGroup != null && !pathGroup.isEmpty()) {
this.pathConfigurationBuilder = this.httpSecurityBuilder.path(pathName, pathGroup);
} else {
this.pathConfigurationBuilder = this.httpSecurityBuilder.path(pathName);
}
}
}
}
}
}
}
}
}
My problem is what is the best way of building configuration similar to above illustrations. I am using reflections to read the value of parameters passed to annotations. But as per the current code, it looks quite heavy and poor because after applying a config, i have to initialize it with an object of same type as the returning object, so, that next config can be applied and the process continues.Is there any better approach ??
EDIT: This occurs during any component AJAX call.
I am building a web application using ICEFaces 3.2.0 community along with Spring Security 3.2 Everything has been going very well up until a few days ago. I have an ACE AutoCompleteEntry component in the page with a backing bean attached to the value as the following example:
<ace:autoCompleteEntry id="autoCompleteState"
label="State"
labelPosition="top"
value="#{autoCompleteEntry.selectedText}"
rows="10" width="160"
filterMatchMode="startsWith">
<f:selectItems value="#{autoCompleteEntry.states}"/>
</ace:autoCompleteEntry>
The backing bean attached is as follows:
#ManagedBean(name=AutoCompleteEntry.BEAN_NAME)
#SessionScoped
public class AutoCompleteEntry implements Serializable {
public static final String BEAN_NAME = "autoCompleteEntry";
public static final String STATE_FILENAME = "State_Names.txt";
public static final String RESOURCE_PATH = "/resources/selectinputtext/";
public AutoCompleteEntry() {
}
public List<SelectItem> states;
public List<SelectItem> getStates() {
if(states == null) {
states = new ArrayList<SelectItem>();
for(String state : readStateFile()) {
states.add(new SelectItem(state));
}
}
return states;
}
private String selectedText = null;
public String getSelectedText() {return selectedText;}
public void setSelectedText(String selectedText) {this.selectedText = selectedText;}
private static List<String> readStateFile() {
InputStream fileIn = null;
BufferedReader in = null;
try {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
fileIn = ec.getResourceAsStream(AutoCompleteEntry.RESOURCE_PATH + STATE_FILENAME);
if(fileIn != null) {
in = new BufferedReader(new InputStreamReader(fileIn));
List<String> loadedStates = new ArrayList<String>(53);
String read;
while((read = in.readLine()) != null) {
loadedStates.add(read);
}
return loadedStates;
}
}catch (IOException failedRead) {
failedRead.printStackTrace();
}finally {
try {
if(in != null) {
in.close();
}
}catch (IOException failedClose) {
failedClose.printStackTrace();
}
}
List<String> errorReturn = new ArrayList<String>(1);
errorReturn.add("Error Loading State List");
return errorReturn;
}
}
The problem is that each time I attempt to test the component instead of bringing up a list of the States it redirects to an absolute path of my main page, which results in a 404. In developer tools I see an error of:
> Uncaught TypeError: Cannot read property 'value' of undefined
bridge.uncompressed.js.jsf:2701
namespace.onAfterUpdate.viewIDElement bridge.uncompressed.js.jsf:2701
apply bridge.uncompressed.js.jsf:122
(anonymous function) bridge.uncompressed.js.jsf:484
(anonymous function) bridge.uncompressed.js.jsf:363
(anonymous function) bridge.uncompressed.js.jsf:240
broadcast bridge.uncompressed.js.jsf:483
(anonymous function) bridge.uncompressed.js.jsf:1928
sendEvent jsf.js.jsf:1447
AjaxEngine.req.sendRequest jsf.js.jsf:1333
request jsf.js.jsf:1834
fullSubmit bridge.uncompressed.js.jsf:2309
submit bridge.uncompressed.js.jsf:2314
iceSubmit compat.uncompressed.js.jsf:1523
onclick
The developer tools log shows:
> [window] persisted focus for element "autoCompleteState_input"
bridge.uncompressed.js.jsf:1252
[window] full submit to localhost:8181/HHCA_Portal/pages/secure/HHCA.jsf
javax.faces.execute: #all
javax.faces.render: patientRecordsForm
javax.faces.source: autoCompleteState_input
view ID: v33tl98j
event type: unknown bridge.uncompressed.js.jsf:1252
XHR finished loading: "localhost:8181/HHCA_Portal/pages/secure/HHCA.jsf".
jsf.js.jsf:1334
AjaxEngine.req.sendRequest jsf.js.jsf:1334
request jsf.js.jsf:1834
fullSubmit bridge.uncompressed.js.jsf:2309
ice.ace.AjaxRequest ace-jquery.uncompressed.js.jsf:20854
ice.ace.ab ace-jquery.uncompressed.js.jsf:20779
ice.ace.Autocompleter.getUpdatedChoices autocompleteentry.js.jsf:695
ice.ace.Autocompleter.onObserverEvent autocompleteentry.js.jsf:637
(anonymous function)
I have spent many hours working on this and other issues, and I have run out of ideas. If someone has some kind of assistance I would really appreciate the help.
If you are using JSF 2 then you can add your own exception handler , this should be able to capture ajax requests.
<factory>
<exception-handler-factory>
test.MyExceptionHandlerFactory
</exception-handler-factory>
</factory>
see the examples here ,
http://balusc.blogspot.com/2012/03/full-ajax-exception-handler.html
http://wmarkito.wordpress.com/2012/04/05/adding-global-exception-handling-using-jsf-2-x-exceptionhandler/
I get the following problem when trying to display a list of items. For each item, I have to display an image which is dynamically loaded via a Wicket WebResource. The items are loaded step by step — 50 at a time — upon user scrolling, using an Ajax scroll.
[ERROR] 2011-04-19 09:58:18,000 btpool0-1 org.apache.wicket.RequestCycle.logRuntimeException (host=, request=, site=):
org.apache.wicket.WicketRuntimeException: component documentList:scroller:batchElem:666:content:item:3:batchItemContent:linkToPreview:imageThumbnail not found on page com.webapp.document.pages.DocumentListPage[id = 1]
listener interface = [RequestListenerInterface name=IResourceListener, method=public abstract void org.apache.wicket.IResourceListener.onResourceRequested()]
org.apache.wicket.protocol.http.request.InvalidUrlException: org.apache.wicket.WicketRuntimeException: component documentList:scroller:batchElem:666:content:item:3:batchItemContent:linkToPreview:imageThumbnail
not found on page com.webapp.document.pages.DocumentListPage[id = 1] listener interface = [RequestListenerInterface name=IResourceListener, method=public abstract void org.apache.wicket.IResourceListener.onResourceRequested()]
at org.apache.wicket.protocol.http.WebRequestCycleProcessor.resolve(WebRequestCycleProcessor.java:262)
at org.apache.wicket.RequestCycle.step(RequestCycle.java:1310)
at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1428)
at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:479)
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816.CGLIB$doGet$6()
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816$$FastClassByGuice$$6d42bf5d.invoke()
at com.google.inject.internal.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:64)
at com.freiheit.monitoring.PerformanceMonitoringMethodInterceptor.invoke(PerformanceMonitoringMethodInterceptor.java:115)
at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:64)
at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:44)
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816.doGet()
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:312)
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816.CGLIB$doFilter$4()
How can this problem be solved?
Here is the part of the code responsible for adding the image:
previewLink.add(createThumbnailSmall("imageThumbnail", documentModel));
in
createThumbnailSmall(final String id, final IModel<BaseDocument> documentModel) {
// thumbnailResource is an object that contains the path of the image
if (thumbnailResource != null) {
final WebResource resource = getWebResource(thumbnailResource);
final Image image = new Image(id, resource);
return image;
}
return new InvisibleContainer(id);
}
WebResource getWebResource(final DocumentResource documentResource) {
return new WebResource() {
private static final long serialVersionUID = 1L;
#Override
public IResourceStream getResourceStream() {
return new BaseStreamResource(documentResource);
}
};
}
where BaseStreamResource is the following:
public class BaseStreamResource extends AbstractResourceStream {
private InputStream _fileInputStream = null;
private DocumentResource _resource = null;
public BaseStreamResource(final DocumentResource documentResource) {
_resource = documentResource;
}
#Override
public InputStream getInputStream() throws ResourceStreamNotFoundException {
if (_fileInputStream == null) {
try {
if (_resource == null) {
throw new ResourceStreamNotFoundException("Resource was null");
}
_fileInputStream = _resource.getFileInputStream();
} catch (final ResourceNotAvailableException ex) {
throw new ResourceStreamNotFoundException(ex);
}
}
return _fileInputStream;
}
In HTML:
<a wicket:id="linkToPreview" href="#">
<img wicket:id="imageThumbnail" alt="Attachment"></img></a>
The code added hasn't really added any clues for me, but maybe I can help narrow it down a bit anyway.
The stacktrace includes a reference to com.webapp.document.pages.DocumentListPage, which is likely calling some of the code you've posted. The error indicates a bad url, so debugging into that class, adding debug prints, and looking at the values of any field containing a url might be worthwhile.
It might even help to modify the code in DocumentListPage (maybe temporarily for debugging) to catch org.apache.wicket.protocol.http.request.InvalidUrlException and adding debugging prints specifically when the exception is caught.
This isn't really an answer, but it's too big for a comment, and maybe it'll help you get closer to an answer.
The following solution solved the problem:
- extend WebResource class
- add extended class as a resource to application shared resources
Ex:
public class MyWebResource extends WebResource {
final ValueMap map = new ValueMap();
#Override
public IResourceStream getResourceStream() {
String fileName = getFileName();
File file = new File(basePath, fileName);
if (!file.exists()) {
LOG.error("File does not exist: " + file);
throw new IllegalStateException("File does not exist: " + file);
}
return new FileResourceStream(file);
}
public final void addResource() {
Application.get().getSharedResources().add(getClass().getName(), this);
}
protected String getFileName() {
return getParameters().getString("id");
}
public final String urlFor(final String fileName) {
final ResourceReference resourceReference = new ResourceReference(getClass().getName());
final String encodedValue = WicketURLEncoder.QUERY_INSTANCE.encode(fileName);
map.add("id", encodedValue);
final CharSequence result = RequestCycle.get().urlFor(resourceReference, map);
if (result == null) {
throw new IllegalStateException("The resource was not added! "
+ "In your Application class add the following line:"
+ "MyConcreteResource.INSTANCE.addResource()");
}
String absoluteUrl = RequestUtils.toAbsolutePath(result.toString());
return absoluteUrl;
}
}
In Application class, in init(), I have added MyWebResource to shared resources:
public void init() {
...
new MyWebResource().addResource();
...
}
I am using TomCat 5.5 with MyFaces 1.1 and am trying to implement a custom regex validation tag.
My RegExValidator class looks like this:
public class RegExValidator implements Validator, StateHolder {
private String regex;
private boolean transientValue = false;
public RegExValidator() {
super();
}
public RegExValidator(String regex) {
this();
this.regex = regex;
}
public void validate(FacesContext context, UIComponent component, Object toValidate) throws ValidatorException {
if ((context == null) || (component == null)) {
throw new NullPointerException();
}
if (!(component instanceof UIInput)) {
return;
}
if (null == regex || null == toValidate) {
return;
}
String val = (String) toValidate;
if (!val.matches(regex)) {
FacesMessage errMsg = MessageFactory.createFacesMessage(context, Constants.FORMAT_INVALID_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, (new Object[]{regex}));
throw new ValidatorException(errMsg);
}
}
public Object saveState(FacesContext context) {
Object[] values = new Object[1];
values[0] = regex;
return (values);
}
public void restoreState(FacesContext context, Object state) {
Object[] values = (Object[]) state;
regex = (String) values[0];
}
public String getRegex() {
return regex;
}
public void setRegex(String regex) {
this.regex = regex;
}
public boolean isTransient() {
return transientValue;
}
public void setTransient(boolean transientValue) {
this.transientValue = transientValue;
}
}
My RegExValidatorTag class looks like this:
#SuppressWarnings("serial")
public class RegExValidatorTag extends ValidatorELTag {
private static String validatorID = null;
protected ValueExpression regex = null;
public RegExValidatorTag() {
super();
if (validatorID == null) {
validatorID = "RegExValidator";
}
}
public Validator createValidator() throws JspException {
FacesContext facesContext = FacesContext.getCurrentInstance();
RegExValidator result = null;
if (validatorID != null) {
result = (RegExValidator) facesContext.getApplication().createValidator(validatorID);
}
String patterns = null;
if (regex != null) {
if (!regex.isLiteralText()) {
patterns = (String) regex.getValue(facesContext.getELContext());
} else {
patterns = regex.getExpressionString();
}
}
result.setRegex(patterns);
return result;
}
public void setValidatorID(String validatorID) {
RegExValidatorTag.validatorID = validatorID;
}
/**
* #param regex
* the regex to set
*/
public void setRegex(ValueExpression regex) {
this.regex = regex;
}
}
My Taglibrary Descriptor looks like this:
<tag>
<name>regexValidator</name>
<tag-class>com.company.components.taglib.RegExValidatorTag</tag-class>
<attribute>
<name>regex</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
My face-common-config.xml has a Validator tag like this:
<validator>
<description>
Validate an input string value against a regular
expression specified by the "regex" attribute.
</description>
<validator-id>RegExValidator</validator-id>
<validator-class>com.company.components.validators.RegExValidator</validator-class>
<attribute>
<description>
The regular expression to test the value against
</description>
<attribute-name>regex</attribute-name>
<attribute-class>java.lang.String</attribute-class>
</attribute>
</validator>
And later on it is supposed to be used in a jsp file like this:
<tc:in value="${dataBean.currentBean.field}">
<a:regexValidator regex="${dataBean.currentBean.validationRegEx}" />
</tc:in>
When calling the page, the following error comes up:
javax.servlet.ServletException: javax.servlet.jsp.JspException: org.apache.jasper.JasperException: Unable to convert string "[\d{4}]" to class "javax.el.ValueExpression" for attribute "regex": Property Editor not registered with the PropertyEditorManager
Caused by:
org.apache.jasper.JasperException - Unable to convert string "[\d{4}]" to class "javax.el.ValueExpression" for attribute "regex": Property Editor not registered with the PropertyEditorManager
I hope I provided enough details for someone to help me out on this...
I seem to have a similar problem like yours, I'm trying to find the solution but seems that the problem is when using Tomcat or the application server(WebSphere Application Server 7.0) JSF libraries, my problem is that the new application server has new JSF libraries (1.2) instead of the 1.1 libraries that my old application server had. (Version 6.1)
To be more specific. my problem is described here. http://www-01.ibm.com/support/docview.wss?uid=swg21318801