Ошибка this value is not valid

I have a problem with a p:selectOneMenu, no matter what I do I cannot get JSF to call the setter on the JPA entity. JSF validation fails with this message:

form:location: Validation Error: Value is not valid

I have this working on several other class of the same type (ie, join table classes) but cannot for the life of me get this one working.

If anyone can throw some troubleshooting/debugging tips for this sort of problem it would be greatly appreciated.

Using log statements I have verified the following:

  1. The Conveter is returning correct, non null values.
  2. I have no Bean Validation in my JPA entities.
  3. The setter setLocation(Location location) is never called.

This is the simplest example I can do and it simply will not work:

<h:body>
    <h:form id="form">
        <p:messages id="messages" autoUpdate="true" />
        <p:selectOneMenu id="location" value="#{locationStockList.selected.location}" converter="locationConverter">
            <p:ajax event="change" update=":form:lblLocation"/>
            <f:selectItems value="#{locationStockList.locationSelection}"/>
        </p:selectOneMenu>
    </h:form>
</h:body>

Converter:

@FacesConverter(forClass=Location.class, value="locationConverter")
public class LocationConverter implements Converter, Serializable {
    private static final Logger logger = Logger.getLogger(LocationConverter.class.getName());

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value.isEmpty())
            return null;
        try {
            Long id = Long.parseLong(value);
            Location location = ((LocationManagedBean) context.getApplication().getELResolver().getValue(context.getELContext(), null, "location")).find(id);
            logger.log(Level.SEVERE, "Converted {0} to {1}" , new Object[] {value, location});
            return location;
        } catch (NumberFormatException e) {
            return new Location();
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value == null || value.toString().isEmpty() || !(value instanceof Location))
            return "";
        return String.valueOf(((Location) value).getId());
    }    
}

Console output:

// Getter method
INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0] 
// Session Bean
INFO: Finding ejb.locations.Location with id=3 
// Session Bean
INFO: ### Returning : ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3] 
// Converter
SEVERE: Converted 3 to ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3] 
// Getter method -> Where did my selected Location go ??
INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0] 

Symfony version(s) affected: 5.0.1

Description

I am getting the weird error description with that hash, with is not very friend human error. I try to google and look at the source at vendor/symfony/form/Extension/Validator/Constraints/Form.php, which I only found a Form contraint called NOT_SYNCHRONIZED_ERROR but no documentation or explanation in docs about which is doing or which cause the origen of this error.

I had a old legacy code inherit from other developer that was using:

$form->handleRequest($request);
$form->submit($request);

At the same time. So submit method probably is not syncronized and raise that error in isValid() form. Should be catched and displayed as global error form in a more friendly way.

footer.html.twig

<div class="col-xl-4 col-md-6 col-lg-4">
						{{ render(controller('App\Controller\FooterNewsletterController::renderNewsletterForm', {'base' : 1})) }}
					</div>

footer_newsletter/index.html.twig

<div class="footer_widget">
							<h3 class="footer_title">Subscribirse</h3>
							<form id="suscriber_footer_form" name="footer_newsletter_type" class="newsletter_form" 
								action="{{ url('newsletter_subscription') }}">
								<input name="email_susbscriber" id="email_susbscriber" type="text" placeholder="Introduce tu email">
								<button name="send_subscriber" id="send_subscriber" type="submit" value="Enviar">Enviar</button>
							</form>
							<p class="newsletter_text">No usaremos tu correo para enviar spam.</p>
						</div>

src/Form/FooterNewsletterType.php

<?php

namespace AppForm;

use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentOptionsResolverOptionsResolver;
use SymfonyComponentValidatorConstraintsEmail;
use SymfonyComponentValidatorConstraintsNotBlank;
use SymfonyComponentFormExtensionCoreTypeEmailType;
use SymfonyComponentFormExtensionCoreTypeSubmitType;

class FooterNewsletterType extends AbstractType
{
    public const EMAIL_FIELD_NAME    = 'email_susbscriber';
    
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
            $builder->add(self::EMAIL_FIELD_NAME, EmailType::class, [
                'required' => true,
                'empty_data'  => '',
                'constraints' => [
                    new NotBlank(),
                    new Email(['mode' => 'strict']),
                ],
            ]);
            $builder->add('send_subscriber', SubmitType::class);
            
            $builder->setMethod(Request::METHOD_POST);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'allow_extra_fields' => true,
            'error_bubbling' => false,
        ]);
    }
    
    public function getBlockPrefix()
    {
        return 'footer_newsletter_type';
    }
}

src/Controller/FooterNewsletterController.php

<?php

namespace AppController;

use AppFormFooterNewsletterType;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentRoutingAnnotationRoute;
use SymfonyComponentHttpFoundationJsonResponse;

class FooterNewsletterController extends AbstractController
{
    /**
     * @Route("/footer/newsletter", name="footer_newsletter")
     */
    public function renderNewsletterForm(Request $request): Response
    {
        $data = [];
        
        return $this->render('footer_newsletter/index.html.twig', [
            $data
        ]);
    }
    
    /**
     * 
     *
     * @Route("/newsletter/suscripcion", name="newsletter_subscription", methods={"POST"})
     */
    public function newsletterSubscribed(Request $request): Response
    {
        $form = $this->createForm(FooterNewsletterType::class, null, ['csrf_protection' => false])->handleRequest($request);
        
        $form->handleRequest($request);
        $form->submit($request); // PROBLEM HERE (second time processed)
            
        if ($request->isMethod('POST') && $request->isXmlHttpRequest()) 
        {

            if ($form->isSubmitted() && $form->isValid())
            {
                [FooterNewsletterType::EMAIL_FIELD_NAME => $email] = $form->getData();
                
                if (empty($email))
                {
                    // Not a spam, save email, etc...
                    //$org = (new Organization())->setName($email);
                    
                    $this->addFlash('success', sprintf('Thank you "%s"! See you later on 🐝️!', 'bla')); /
                }
                else
                {
                    // Spam detected!
                    $warning = sprintf('🐛 SPAM detected: email: "%s", honeypot content: "%s"', $email, 'blo');
                    $this->addFlash('warning', $warning);
                }
                
                return new JsonResponse('Form valid ' . print_r($form->getData(), TRUE), 200);
            }
            else
            {
                $errors = [];
                foreach ($this->getErrors(true) as $error)
                 {

 var_dump((string)$error->getMessage());
var_dump((string)$error->getCause());
var_dump((string)$error->getOrigin());

var_dump((string)$error->getMessageTemplate());
var_dump((string)$error->getMessageParameters());


}

var_dump((string)($this->getErrors(true)));exit;

                $response = new JsonResponse('', 200);
                $response->setData('errors', print_r($errors, TRUE));
                return $response;
            }
            
        }
        
        
    }
}

Javascript

if($( "#suscriber_footer_form" ))
		{
        		$( "#suscriber_footer_form" ).submit(function( event ) 
                {	
                	  event.preventDefault();

                	  var form = $('#suscriber_footer_form')[0]; // You need to use standard javascript object here
                	  var formData = new FormData(form);
                	  
                	  $.ajax({
                        type: "POST",
                        url: $(this).attr("action"),
                        data: formData + '&send_subscriber=true',
                        processData: false,
    					contentType: false,
    					cache: false,
                        success: (data) => 
                        {
                        	console.log('Submission was successful.');
                			console.log(data);
                
                            $('#popup-box-content').html('<p style="text-align: center">Thank you for ' +
                            'subscribing to The Polyglot Developer newsletter!</p>');
                        },
                        error: function (data) {
                            console.log('An error occurred.');
                            console.log(data);
                        },
                    });
                	  
                	  
                	  
                });
         }

Output:

string(24) "This value is not valid."
string(109) "Object(SymfonyComponentFormForm):
    This value is not valid. (code 1dafa156-89e1-4736-b832-419c2e501fca)"

Possible Solution
Detect when submit is called after handleRequest or improve error messaging to be more friendly

Additionally. Using only:

$form->submit($request);

Produces the error also of no syncronized.

Using only:

$form->handleRequest($request);

Will detect the form as NO subbmited.

And using:

$form->handleRequest($request);
$form->submit($request);

Will produce no syncronized.

At some point the form send via ajax is not picking the values after form submition.

Dear Dandu , glad to see that i m not alone fighting this problem , i personally discovered this bug in October 2022

and posted Video on https://github.com/PrestaShop/PrestaShop/issues/30042#issuecomment-1556546158

when no one nobody believed in this bug , i try trillion of solutions but until now nothing to do , even because if you go on debug you won’t find errors in reference

i m sure that problem is located in classes/product.php

I appreciate if we can stay in touch in order to solve this matter.

Thanks

Maurizio

Skip to content

This is one problem i faced when i worked with select-many and select-one menus in Java Server Faces. For any one who have worked with JSF knows that you have to use custom converters in order to populate select-many and select-on menus with ur own data types.

if i elaborate on this a little bit, Select menus are not just there to show simple value-label pairs. you can give directly an object to its value and one of its fields as the label. for an example,

public ArrayList<SelectItem> getLandSelectList() {
if (landSelectList != null) {
return landSelectList;
}
    landSelectList = new ArrayList<SelectItem>();
List<Land> landList = this.getLandList();
for (int i = 0; i < landList.size(); i++) {
        landSelectList.add(new SelectItem(landList.get(i), landList.get(i)
.getLandsName_DE()));
}
return landSelectList;
}

The returning Select list can be taken to a select one or a select many list box like..

<h:selectOneMenu id=”listBoxLand
value=”#{userManagerBean.land}” required=”true”>
<f:selectItems value=”#{userManagerBean.landSelectList}” />
</h:selectOneMenu>
<h:message for=”listBoxLand” />

This component will set the selected land object directly to the backing bean. If you used simple value(some text or the id) – label pair. you should again query for the object from the selected id and save in the backing bean. but in this way that extra trouble will be handled by JSF.

The problem is if you do it just like this with out anything else.. you will get a wired validation error saying “Validation Error: Value is not valid“. This is where you start googling and debugging. Well after some hours of googling..(couldn’t do much debugging because this is a exception thrown by JSF framework) and reading about 10 to 20 forums i found out that the object which is loaded and the object wich was selected will be compared when setting to the backing bean. So if your object’s Class has not overridden the equals method this error message is shown.

So what you have to do is. if you are using your own data Objects for the select menus or in that case for any other JSF tag where you will use converters. You have to override the Equals method. Probably do the comparison with the Id, or with some unique value in that data Object. That’s it.. The problem solved. In my case the equals methods looks like

// overridden equals method
public boolean equals(Object obj) {
if (!(obj instanceof Land)) {
return false;
}
Land land = (Land) obj;

return (this.id == land.id);

}

Yeah hope this will be useful to some one.. !! I will write another post on how to use Java Collections when working with Select-Many menus.

  • Solved Questions
  • This Question

CloudMikeCloudMike

Validation Error: Value is not valid — One Cause/Solution

I recently ran into a problem where a Visualforce page was throwing a cryptic error message related to a custom picklist (apex:selectList).  The complete error was something like:

j_id0:frmSelectProductsServicesw:filterSection:j_id10:j_id15:selectedPF:Validation Error: Value is not valid

After some digging and research here in the forums, testing and a call to Tech Support it seemed the cause and solution for similar problems didn’t quite apply.  I eventually found the solution (in my case) and wanted to share it in hopes that it would help others.

The cause was due to a conflict between the underlying stored data in SFDC and how certain controls behave when rendered to HTML.  In this case, there was a double space embedded in the underlying data between the Z and I in the value Product.Family field (eg. ‘S&U Z  Internal’). 

Background:

  1. For Visualforce controls (ie. apex.outputField, apex.outputText, apex:selectList) and modes (ie. edit and view), every control ultimately must renders as HTML.  Typical HTML rendering behavior suppresses any extra spaces within text.  That is why it is common practice to use the &nbsp to chain multiple spaces together. 
  2. In this case, the underlying stored data in the Product.Family field included a double space:
          ‘S&U Z  Internal’
    however when it was rendered to the screen, the HTML took control and used only a single space:
          ‘S&U Z Internal’
  3. Once the user clicked the submit button to begin the search, the picklist in this case tried to cross-reference the selected value with the actual data that was bound to the control and found no match, thus the cryptic error that was returned — “selectedPF:Validation Error: Value is not valid”.
          ‘S&U Z  Internal’ != ‘S&U Z Internal’

Funny thing is, when the underlying data is rendered in a input textbox (ie. apex.inputText), the double space is displayed.  Once I removed the double space from the underlying data, the error was fixed.

Hopefully this solution helps.

Thanks to Sreenivas Voore in Premiere Tech Support.

You need to sign in to do that.

Dismiss

Понравилась статья? Поделить с друзьями:
  • Ошибка this server has mods that require
  • Ошибка this request is forbidden
  • Ошибка this program requires the file advrcntr5 dll
  • Ошибка this operating system is not supported
  • Ошибка this method is not allowed for anonymous call