I have one-to-many
relationship between two entities TypeSite
and Site
. On the front end i have a form (angularJS) used for creation of a new Site with a bunch of fields and drop-down list where user can select type of this site. The form submit successfully without Dropdown
,but when i try submit the form with the combobox i get the following error :
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'site' on field 'siteesTypeSite': rejected value [Etatique]; codes [typeMismatch.site.siteesTypeSite,typeMismatch.siteesTypeSite,typeMismatch.model.TypeSites,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [site.siteesTypeSite,siteesTypeSite]; arguments []; default message [siteesTypeSite]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'model.TypeSites' for property 'siteesTypeSite'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [model.TypeSites] for property 'siteesTypeSite': no matching editors or conversion strategy found]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:110)
Model :
public class Sites implements java.io.Serializable {
private int id;
private TypeSites siteesTypeSite;
@JsonBackReference("site-typeSite")
@ManyToOne
@JoinColumn(name = "idTypeSite")
public TypeSites getSiteesTypeSite() {
return siteesTypeSite;
}
public class TypeSites implements java.io.Serializable {
private int idTypeSite;
private Set<Sites> sitees= new HashSet<Sites>(0);
@JsonManagedReference("site-typeSite")
@OneToMany(mappedBy = "siteesTypeSite",fetch = FetchType.LAZY)
public Set<Sites> getSitees() {
return sitees;
}
Repository :
public interface SitesRepository extends PagingAndSortingRepository<Sites, Integer> {
Page<Sites> findBycodeGSMLike(Pageable pageable, String codeGSM);
}
Services class :
@Service
@Transactional
public class SitesService {
@Autowired
private SitesRepository siteRepository;
@Transactional(readOnly = true)
public void save(Sites site) {
siteRepository.save(site);
}
}
controller class :
@Controller
@RequestMapping(value = "/protected/sites")
public class SitesController {
private static final String DEFAULT_PAGE_DISPLAYED_TO_USER = "0";
@RequestMapping(method = RequestMethod.GET)
public ModelAndView welcome() {
return new ModelAndView("sitesList");
}
@RequestMapping(method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<?> create(@ModelAttribute("site") Sites site,
@RequestParam(required = false) String searchFor,
@RequestParam(required = false,
defaultValue = DEFAULT_PAGE_DISPLAYED_TO_USER) int page,
Locale locale) {
siteService.save(site);
if (isSearchActivated(searchFor)) {
return search(searchFor, page, locale, "message.create.success");
}
return createListAllResponse(page, locale, "message.create.success");
}
}
Angularjs code : $scope.createObject = function (newObjectForm) { if (!newObjectForm.$valid) { $scope.displayValidationError = true; return; } $scope.lastAction = 'create';
var url = $scope.url;
var config = {headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}};
$scope.addSearchParametersIfNeeded(config, false);
$scope.startDialogAjaxRequest();
$http.post(url, $.param($scope.sites), config)
.success(function (data) {
$scope.finishAjaxCallOnSuccess(data, "#addObjectsModal", false);
})
.error(function(data, status, headers, config) {
$scope.handleErrorInDialogs(status);
});
};
On the JSP :
<select ng-model="sites.siteesTypeSite"
name="siteesTypeSite"
ng-options="typesites as typesites.typeSite for typesites in page.source "
value="{{sites.siteesTypeSite}}" >
<option value="">-- Select Type site --</option>
<input type="hidden" name="siteesTypeSite" value="{{sites.siteesTypeSite}}" />
</select><br>
Your error is explained in the stacktrace : Failed to convert property value of type 'java.lang.String' to required type '.model.TypeSites' for property 'siteesTypeSite';
The value in the dropbox is a string and you are trying to match a TypeSites.
Solution:
I suppose your TypeSites is an Enum. If that's the case just create a function to find the matched value based on the string returned by the dropdown.
Create a field siteesTypeSiteName and update your dropbox like I did. Then use the function to get the linked TypeSites.