I have a form in tml file of a Tapestry component.
...
<t:form t:id="searchForm" clientValidation="none">
....
<t:select t:id="globalSport" model="globalSportModel" value="formData.globalSportId" blankOption="never"/>
....
</t:form>
..
And here is the important part of corresponding Java file:
...
#Property(read = true, write = false)
private ServiceSearchFormData formData;
...
#OnEvent(value = EventConstants.PREPARE_FOR_SUBMIT, component = "searchForm")
void prepareForSubmit()
{
formData = new ServiceSearchFormData();
}
...
It seems to be pretty straightforward. ServiceSearchFormData is a DTO with few attributes and getter / setter methods. It encapsulates data submitted in the form. An instance is created on "prepare for submit" event. ... and it works fine.
However, an exception is thrown in production environment occasionally. I am not able to reproduce it. It happens in scope of POST request that submits data to this form. The exception message states:
Failure writing parameter 'value' of component MyPortal:portalindex.portalsearchform.globalsport: Property 'formData' (within property expression 'formData.globalSportId', of cz.ftm.fitsoftware.webapp.components.PortalSearchForm#3262579e) is null.
How is that possible? How can the property formData be uninitialized? Can this rare (but regular) exception be caused by malformed value of t:formdata parameter of POST request?
Thanks for any help.
Based on this much I can see, I would try two things to narrow down the problem:
I would remove the component = "searchForm" qualifier
#OnEvent(value = EventConstants.PREPARE_FOR_SUBMIT)
void prepareForSubmit()
{
formData = new ServiceSearchFormData();
}
I would remove all the other #OnEvent annotations to see if any of those swallows this event:
//#OnEvent(...)
void foo() {...}
Related
I am using Spring 4 + Jackson 2 and have written a fully functional POST method using #RequestBody on a custom class. This method has no trouble unmarshalling the object.
#ResponseBody
#RequestMapping(value="store", method = RequestMethod.POST)
public ServiceResponse store(#RequestBody CustomClass list) {
...
}
// Request: { code: "A", amount: 200 }
When I attempted to add another method to handle a collection of the same class instead, my POST requests were returning with the following error.
HTTP Status 400: The request sent by the client was syntactically incorrect.
I note that this error typically occurs when the JSON submitted does not match the entity class. However, all I am doing is submitting an array of the same object instead of the object itself, which has already proven to work.
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody List<CustomClass> list) {
...
}
// Request: [{ code: "A", amount: 200 }, { code: "B", amount: 400 }]
Am I missing something here?
In Java, type information for generics is erased at runtime, so Spring sees your List<CustomClass> object as List<Object> object, thus it cannot understand how to parse it.
One of ways to solve it, you could capture the type information by creating a wrapper class for your list, like this:
public class CustomClassList extends ArrayList<CustomClass> {
}
Sergey is right that the issue is due to type erasure. Your easiest way out is to bind to an array, so
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody CustomClass[] object) {
...
}
The answer is that Spring 4 doesn't actually get rid of type erasure, contrary to what some other solutions suggest. While experimenting on debugging via manual unmarshalling, I decided to just handle that step myself instead of an implicit cast that I have no control over. I do hope someone comes along and proves me wrong, demonstrating a more intuitive solution though.
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody String json) {
try {
List<CustomClass> list = new ObjectMapper().readValue(json, new TypeReference<List<CustomClass>>() { });
...
} catch (Exception e) {
...
}
}
Bonus: Right after I got this working, I bumped into this exception:
IllegalStateException: Already had POJO for id
If anyone gets this, it's because the objects in the list happen to reference some object that another item in the list already references. I could work around this since that object was identical for my entire collection, so I just removed the reference from the JSON side from all but the first object. I then added the missing references back after the JSON was unmarshalled into the List object.
Two-liner for the Java 8 users (the User object reference was the issue in my case):
User user = list.get(0).getUser();
list.stream().filter(c -> c.getUser() == null).forEach(t -> t.setUser(user));
I have some custom (logic-)validators for Eclipse, but all are facing the same Problem:
The actual implementation of some logic can take place in any of the parent classes.
So, whenever a resource in question changes, I can went up the inheritance tree to see if the required code takes place in any of the parent classes - if not, i'm placing a marker into the validated file itself.
This marker ofc. gets verified, whenever changes to the resource in question are made. But how can i trigger a revalidation if one of the parent classes changes?
Is it possible to place some kind of "validator-callback" into other files, which will trigger an validation of the given file?
i.e. Three Classes: A extends B, B extends C - Now, the validator notes on A, that neither A nor B nor C is extending X - which is required for A due to annotations. (Logic-Contract)
Now the Error-Marker in A should be re-evaluated as soon as B or C are modified. (Currently i'm using a delta-builder which ofc. just will invoke validation whenever A changes...)
In a nutshell: I want to place a "marker", that gets re-validated whenever one out of X resources change.
After I had some time to play around, I finally found a 99% solution to this issue.
Good news: It is possible.
Bad news: It is DIY. I was not able to find any useful method to achieve what I want.
The following post should outline the solution regarding my problem. There might be better, more efficent or easier solutions, but unfortunately the documentation around the validation framework of eclipse is very thin - so i'd like to share my solution - take it, improve it - or ignore it :)
First, you should understand the actual problem I tried to solve. Therefore I'm providing short snippets, without going into too much detail of the validator or my code-lineout:
In my project, I'm using Hibernate - and therefore a lot of classes annotated with #Entity. When using Hibernate along with LazyLoadingone needs to (manually) ensure, that PersistentBags are initialized when accessed.
In our application, there is a method called initializeCollection(Collection c) in the class LazyEntity, which handles everything around it.
This leads to a logic contract my validator should validate:
Whenever there is a class annotated with #Entity, AND this class is using FetchType.LAZY on any of its collections, there musst be two contraints met:
A.) the class - or any of its ancestors - needs to extend LazyEntity.
B.) the getter of the collection in question needs to call initializeCollection() before returning the collection.
I'll focus on point B, because this is, where the validation problem kicks in: How to revalidate an actual Entity, when it's ancestor changes?
I modified the actual validation method, to have two IFiles as Attributes:
public void checkLazyLoadingViolations(IFile actualFile, IFile triggeredFile) {
//validation of actualFile takes place here
}
The delta-builder as well as the incremental builder are invoking this method like this:
class LazyLoadingResourceVisitor implements IResourceVisitor {
public boolean visit(IResource resource) {
if (resource instanceof IFile) {
checkLazyLoadingViolations((IFile) resource, (IFile) resource);
}
// return true to continue visiting children.
return true;
}
}
Now - in a first step - the validator itself is taking care to validate the actualFile and bubbling up the inheritence tree to validate any parent file as well. If the validator hits the top-most-parent, without finding the required extension, an additional marker is placed.
The placement of the markers is happening with the following method. In case the file, where the marker should be placed differs from the file on which eclipse has invoked the validation, the IMarker.USER_EDITABLE Attribute is used to store a path to the file, on which the validation has been invoked (in order to retrigger validation):
/**
* Creates a Marker in the give IFile, considering if it should be a direct
* marker, or a dependency marker, which our Validator can resolve later.
*
* #param actualFile
* The file that is currently validated.
* #param triggeredFile
* The file on which eclipse invoked the validation.
* #param message
* The message for the Marker.
* #param lineNumber
* the line number, where the Marker should appear.
* #param severity
* the severity of the marker.
* #param callbackPath
* The full path to the file that should be validated, when the
* marker is revalidated.
*/
public void addMarker(IFile actualFile, IFile triggeredFile,
String message, int lineNumber, int severity, String callbackPath) {
try {
IMarker marker = actualFile.createMarker(MARKER_TYPE);
marker.setAttribute(IMarker.MESSAGE, message);
marker.setAttribute(IMarker.SEVERITY, severity);
marker.setAttribute(IMarker.LINE_NUMBER, lineNumber == -1 ? 1
: lineNumber);
if (callbackPath != null) {
marker.setAttribute(IMarker.USER_EDITABLE, "callback:"
+ triggeredFile.getFullPath());
}
} catch (CoreException e) {
// eclipse made a boo boo.
}
}
Now, the validation errors are set: Each actual class contains its Errors - and in case the validation fails in the inheritance tree, the parent contains a marker as well:
(AdminUser extends TestUser in this Example)
When the validator gets triggered on the "parent" file due to changes, it graps all markers, and checks, if the marker provides the callback Attribute. If so, the validator invokes the validation of the resource instead of just validating the parent:
IMarker[] markers = null;
try {
markers = actualFile.findMarkers(IMarker.PROBLEM, true,
IResource.DEPTH_INFINITE);
for (IMarker m : markers) {
// Our marker type?
if (m.getType().equals(MARKER_TYPE)) {
// dependent resource defined?
if (m.getAttribute(IMarker.USER_EDITABLE) != null) {
if (m.getAttribute(IMarker.USER_EDITABLE)
.toString().startsWith("callback:")) {
String otherFile = m
.getAttribute(IMarker.USER_EDITABLE)
.toString().replace("callback:", "");
// call validation for that file as well.
// (recursion)
String relOther = otherFile.split(Pattern.quote(actualFile.getProject().getFullPath().toString()))[1];
IFile fileToValidateAsWell = actualFile
.getProject().getFile(relOther);
//remove old markers!
deleteMarkers(fileToValidateAsWell);
//revalidate - which has no impact but triggering the root-resource again!
//this will recreate the just deleted markers if problem is not resolved.
checkLazyLoadingViolations(
fileToValidateAsWell, triggeredFile);
}
}
}
}
} catch (CoreException e1) {
}
Finally, a change to the root file in the inheritance tree causes the leaf file to be revalidated:
And ofc. when calling the initializeCollection-Method properly, there is no error at all :)
The only trade off so far is: IF the parent-file is valid - and gets modified to invalid - it will not re-trigger the validation of the leaf, because there is no error-marker containing any callback information.
The error then will appear the first time a full-build is performed. - For the moment, I can live with that.
Logic in a nutshell
If the validated resource is a leaf:
Place markers in the leaf
Place marker in the top-most-parent, while adding a callback link as marker attribute.
If the validated resource is a root
Remove markers
call validation on the linked leaf provided by the callback link inside the existing marker, which in trun will be case 1 and recreate all markers if applicable.
I am trying parse a HL7 REF I12 message with local customization(NZ).
When I tried using the GenericParser, I keep getting Validation exceptions.
For example for the segment below, I keep get the output
ca.uhn.hl7v2.validation.ValidationException: Validation failed:
Primitive value '(08)569-7555' requires to be empty or a US phone
number
PRD|PP|See T Tan^""^""^^""|""^^^^""^New Zealand||(08)569-7555||14134^NZMC
My question is:
Is there a way to avoid the validation by using the conformance class
generator
Is it possible to create own validation classes using
CustomModelClasses?
In either case, is there any example code for that or tutorial example documentation?
If disabling validation altogether is an option for your application, then you can set the validation context to use NoValidation.
See this thread in the hapi developers mailing list: http://sourceforge.net/p/hl7api/mailman/message/31244500/
Here is an example of how to disable validation:
HapiContext context = new DefaultHapiContext();
context.setValidationContext(new NoValidation());
GenericParser parser = context.getGenericParser();
String message = ...
try {
parser.parse(message);
} catch (Exception e) {
e.printStackTrace();
}
If you still require validation, but just want to change the validator for specific rules, then you'll have to create your own implementation of ValidationContext. This would be done by sub classing ca.uhn.hl7v2.validation.builder.support.NoValidationBuilder and overriding the configure method and use this to instantiate an instance of ValidationContextImpl.
For an example of how to implement the configure method in your subclass of NoValidationBuilder, see the source code for ca.uhn.hl7v2.validation.builder.support.DefaultValidationBuilder. This is the default validation context that is generating the error message you're seeing. To make it easier for you, I'm including the class listing here:
public class DefaultValidationBuilder extends DefaultValidationWithoutTNBuilder {
#Override
protected void configure() {
super.configure();
forAllVersions()
.primitive("TN")
.refersToSection("Version 2.4 Section 2.9.45")
.is(emptyOr(usPhoneNumber()));
}
}
Notice this is the implementation of the usPhoneNumber method defined in BuilderSupport:
public Predicate usPhoneNumber() {
return matches("(\\d{1,2} )?(\\(\\d{3}\\))?\\d{3}-\\d{4}(X\\d{1,5})?(B\\d{1,5})?(C.*)?",
"a US phone number");
}
When attempting to edit a new (proxy) entity using RequestFactoryEditorDriver.edit() I am getting the following error: "Exception caught: Attempting to edit an EntityProxy previously edited by another RequestContext". I am fairly sure that this is a result of my misunderstanding of the request factory/editor framework architecture. Here is the editor code that I think pertains to this problem:
public class OrgMaintenanceWidget extends Composite implements Editor<IOrgProxy> {
... other fields ...
private IOrgEditorDriver _orgEditorDriver;
interface IOrgEditorDriver extends RequestFactoryEditorDriver<IOrgProxy, OrgMaintenanceWidget> {}
public OrgMaintenanceWidget(final IClientFactory clientFactory) {
... widget initialization ...
_orgEditorDriver = GWT.create(IOrgEditorDriver.class);
_orgEditorDriver.initialize(_clientFactory.getRequestFactory().getEventBus(),
_clientFactory.getRequestFactory(), this);
}
#UiHandler("newButton")
public void onNewButtonClick(final ClickEvent clickEvent) {
_org = _clientFactory.getCache().getOrgCache().newOrg();
_orgEditorDriver.edit(_org, _clientFactory.getRequestFactory().orgRequestContext());
}
...
}
It's the "_orgEditorDriver.edit()" line that causes the exception. The "newOrg()" method is:
public IOrgProxy newOrg() {
return _clientFactory.getRequestFactory().orgRequestContext().create(IOrgProxy.class);
}
The RequestFactory is simply:
public interface IRequestFactory extends RequestFactory {
IOrgRequestContext orgRequestContext();
}
I am sure that I'm missing something fundamental about editing a new entity. When I edit an existing entity everything is fine ... the UI components are populated automatically, and flushing the editor back to the entity works very nicely. Here's the code that initiates editing for an existing entity:
#UiHandler("newButton")
public void onNewButtonClick(final ClickEvent clickEvent) {
_org = _clientFactory.getCache().getOrgCache().newOrg();
_orgEditorDriver.edit(_org, _clientFactory.getRequestFactory().orgRequestContext());
}
Any help would be greatly appreciated, and I'll try to publish any lessons learned.
This code:
_clientFactory.getRequestFactory().orgRequestContext().create(IOrgProxy.class);
Means:
Create new orgRequestContext()
Create new IOrgProxy using this context
Edit new IOrgProxy using this context, because as docs say: "Returns a new mutable proxy that this request can carry to the server, perhaps to be persisted.", it means that the proxy is edited by this request.
This code:
_orgEditorDriver.edit(_org, _clientFactory.getRequestFactory().orgRequestContext());
Means:
Again, create new orgRequestContext() (because each invocation of getRequestFactory().orgRequestContext() provides new instance of orgRequestContext()
"Start driving the Editor and its sub-editors with data." as docs say. But as a part of it, use passed orgRequestContext() to edit passed IOrgProxy instance, so that the proxy is editable.
Because the proxy was already edited while created by other RequestContext, you get the exception, because there is fundamental rule in RequestFactory, that proxy can be edited only by one RequestContext.
See also this thread.
I think you can't create an object with one RequestContext and then edit it with another one.
So you can solve this in two ways:
Persist the created object with the RequestContext you used when you created the object. The save method should return the persisted object and this persisted object can be passed to the editor with a fresh new RequestContext
Somewhere save the RequestContext you used for creating the object and pass it to the edit function of your Driver
Solution two could look something like this:
#UiHandler("newButton")
public void onNewButtonClick(final ClickEvent clickEvent) {
IOrgRequestContext ctx = _clientFactory.getRequestFactory().orgRequestContext();
_org = ctx.create(IOrgProxy.class);
_orgEditorDriver.edit(_org,ctx );
}
Is there a simple way in Symfony 1.4 to know whether a submitted form had any errors inside the form class? I'm familiar with the $form['some_field']->hasErrors() for templates but in this case I'd like to run a post-validator only if the form didn't have any errors with the standard validators. I'm basically after something like:
public function configure() {
// widgets
// standard validators
if (!this->hasErrors()) {
// run post-validator
}
}
The API documentation is as cryptic as usual. Thanks in advance.
Since the validation is perfom on the bind call, I don't see other place to post validate on error than in the bind function. So, in your form class:
public function bind(array $taintedValues = null, array $taintedFiles = null)
{
parent::bind($taintedValues, $taintedFiles);
if ($this->hasErrors())
{
// do post validate
// you can access values from your form using $taintedValues
}
}
But you will have to manually call the validator instead of just define a new one (since the bind process has already been done).