Spring 2.5 to 3.2 upgrade error: Invalid property 'commandClass' of bean class - spring-3

I am new to Spring and am upgrading a Spring 2.5 web app to 3.2.3. I am getting an error navigating off the front page of the app.
The error is Invalid property 'commandClass' of bean class. This web app has been running for about 5 years, so the
issue has to be the Spring 2.5 to 3.2 changes. I must have something wired wrong, any ideas?
The full error is :
Error creating bean with name '/new_candidate.html' defined in ServletContext resource [/WEB-INF/webapp-servlet.xml]:
Error setting property values;
nested exception is org.springframework.beans.NotWritablePropertyException:
Invalid property 'commandClass' of bean class [org.myorg.app.web.ScoreChangeController]:
Bean property 'commandClass' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?
Here is the bean def from the webapp-sevlet.xml:
<bean name="/new_candidate.html" class="org.myorg.app.web.ScoreChangeController" scope="session">
<property name="commandClass" value="org.myorg.app.model.Database"/>
<property name="formView" value="generic"/>
<property name="candidateManager" ref="candidateManager"/>
</bean>
The controller is:
package org.myorg.app.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.myorg.app.model.Database;
import org.myorg.app.service.CandidateManager;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.validation.BindException;
import org.springframework.web.util.WebUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
public class ScoreChangeController
{
private CandidateManager candidateManager;
protected Object formBackingObject(HttpServletRequest request) throws Exception {
Database defaultDatabase = new Database();
defaultDatabase.setApptNo("16 digits");
defaultDatabase.setAccessionNo("8 digits");
defaultDatabase.setTstPkgId("12345678912345678912345");
return defaultDatabase;
}
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
Database database = (Database)binder.getTarget();
}
public CandidateManager getCandidateManager() {
return candidateManager;
}
public void setCandidateManager(CandidateManager candidateManager) {
this.candidateManager = candidateManager;
}
public ModelAndView onSubmit(HttpServletRequest req, HttpServletResponse res, Object command, BindException errors) throws Exception {
if(WebUtils.hasSubmitParameter(req, "retrieve"))
{
candidateManager.retrieveData((Database)command);
}
return new ModelAndView(new RedirectView("success.jsp"));
}
}

You are trying to inject property commandClass inside the ScoreChangeController bean, but i am not able to see any property with that name in that controller and moreover it is not a subclass of any specific controller also so no chance of inheritance also.
Solution : Either remove the injection of commandClassproperty from the ScoreChangeController bean .
<bean name="/new_candidate.html" class="org.myorg.app.web.ScoreChangeController" scope="session">
<property name="formView" value="generic"/>
<property name="candidateManager" ref="candidateManager"/>
OR create a new property in your ScoreChangeController having the name as command and create the setters and getters for that.

Related

How to have Spring ContextConfiguration load both from XML and from JavaConfig

From what I've read of the Spring #ContextConfiguration annotation, it's possible to load multiple XML context files, or multiple JavaConfig classes. What I need is to load from one XML context file and one class. All the examples I've seen either load all XML, or all classes, but not both.
I'm trying to do this because I want my test class, which is just there to verify expected Spring wiring, to load my default applicationContext.xml file (presently just a copy stored in "src/test/resources, and trying to figure out how to directly specify the default one) along with a JavaConfig class that specifies some JNDI resources that need to be available. For the purposes of my test, I only need to set those JNDI resources to dummy strings, but I'd really like to specify them in an inline static class instead of an external XML file, because my tests are going to have to verify that some settings are equal to those dummy strings, and it's more maintainable if both the values and the checks are in the same file.
What I have so far, and what I've tried, can be illustrated with this:
#RunWith(SpringRunner.class)
#ContextConfiguration(value = {"/testApplicationContext.xml", "/testResources.xml"})
//#ContextHierarchy({
// #ContextConfiguration("/testApplicationContext.xml"),
// #ContextConfiguration(classes = SpringWiringTest.Config.class)
//})
#TestPropertySource(properties = { "env = tomcat", "doNotifications = false" })
public class SpringWiringTest {
And this at the end of the class:
#Configuration
public static class Config {
#Bean public String uslDatasourcesList() { return "abc"; }
#Bean public String atgDatasourcesList() { return "abc"; }
#Bean public String uslTableNamePrefixsList() { return "abc"; }
#Bean public String atgTableNamePrefixsList() { return "abc"; }
#Bean public String doNotifications() { return "false"; }
#Bean public DataSource abc() { return new DriverManagerDataSource(); }
}
If I comment out the first #ContextConfiguration and comment back in the #ContextHierarchy block, I get an error like this:
Error creating bean with name 'uslDatasourcesList': Invocation of init
method failed; nested exception is
javax.naming.NoInitialContextException: Need to specify class name in
environment or system property, or as an applet parameter, or in an
application resource file: java.naming.factory.initial
Update:
Using the guideline of picking either JavaConfig or XML as the "entry point" to configuration, here are some modified excerpts that show what I'm trying:
#RunWith(SpringRunner.class)
#ContextConfiguration
//#ContextConfiguration(value = {"file:src/main/webapp/WEB-INF/applicationContext.xml", "/testResources.xml"})
#TestPropertySource(properties = { "env = tomcat", "doNotifications = false" })
public class SpringWiringTest {
...
#BeforeClass
public static void setup() throws Exception {
SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
DataSource ds = new DriverManagerDataSource();
builder.bind("java:comp/env/abc", ds);
}
...
#Configuration
#ImportResource("file:src/main/webapp/WEB-INF/applicationContext.xml")
public static class Config {
#Bean public String uslDatasourcesList() { return "abc"; }
#Bean public String atgDatasourcesList() { return "abc"; }
#Bean public String uslTableNamePrefixsList() { return "abc"; }
#Bean public String atgTableNamePrefixsList() { return "abc"; }
#Bean public String doNotifications() { return "false"; }
#Bean public DataSource abc() { return new DriverManagerDataSource(); }
}
}
When I run my test, the bottom "Caused by" in the exception says this:
Caused by: javax.naming.NameNotFoundException: Name
[uslDatasourcesList] not bound; 1 bindings: [java:comp/env/abc]
In the alternate version, using the commented-out "#ContextConfiguration" (and commenting out the Config class and its annotations), this error does not occur.
Note that this the meat of my "testResources.xml" file:
<bean id="uslDatasourcesList" class="java.lang.String"> <constructor-arg value="abc"/> </bean>
<bean id="atgDatasourcesList" class="java.lang.String"> <constructor-arg value="abc"/> </bean>
<bean id="uslTableNamePrefixList" class="java.lang.String"> <constructor-arg value="abc"/> </bean>
<bean id="atgTableNamePrefixList" class="java.lang.String"> <constructor-arg value="abc"/> </bean>
<bean id="doNotifications" class="java.lang.String"> <constructor-arg value="false"/> </bean>
<bean id="abc" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
</bean>
Note that the bean mentioned in the error message, "uslDatasourcesList" is defined in both versions, but it's not working in the version with JavaConfig and XML mixed.
It almost appears that the beans in the "#ImportResource" annotation are evaluated on their own, before the beans declared in the JavaConfig class are merged into it.
This is clearly documented in the Spring Reference Manual in the section named Mixing XML, Groovy scripts, and annotated classes.
In summary, ...
... you will have to pick one as the entry point, and that one will have to include or import the other.
Thus, the following should hopefully solve your problem.
#RunWith(SpringRunner.class)
#ContextConfiguration
#TestPropertySource(properties = { "env = tomcat", "doNotifications = false" })
public class SpringWiringTest {
// ...
#Configuration
#ImportResource({"/testApplicationContext.xml", "/testResources.xml"})
static class Config {
// ...
}
}

Spring Integration - XML Schema validator - Dynamic schema file selection

I am trying to implement XML validation using Spring Integration <int-xml:validating-filter />. I followed the discussion in usage of spring integration's schema validator?. The problem statement is the same but with an additional parameter. Instead to hard coding the value in schema-location="xyz.xsd", rather I want to dynamically select the appropriate xsd file for respective incoming xml or DOMSource inputs.
I also followed http://forum.spring.io/forum/spring-projects/integration/121115-dynamic-schema-location-for-xml-validating-filter-component where Gary Russell mentioned:
There's no direct support for dynamic schemas, but you can provide a
custom XmlValidator using the xml-validator attribute (mutually
exclusive with schema location)
Once you've introspected your document to find the schema you wish to
validate against, simply delegate to a validator that has been
configured to validate against that schema.
You can use a XmlValidatorFactory to create each validator; see the
XmlValidatingMessageSelector for how to create a validator, once you
know the schema location
Since the comments dates back to the year 2012, is there an approach now in spring integration to validate input xml by dynamically selecting appropriate schema? If not can anyone provide an example on how to implement?
Following is my spring integration configuration:
<int:gateway id="applicationServiceGateway" service-interface="abc.IGateway"
default-request-channel="applicationRequestChannel" default-reply-channel="applicationResponseChannel"
error-channel="errorProcessingChannel" />
<int:chain id="serviceRequestValidation" input-channel="applicationRequestChannel" output-channel="responseChannel">
<!-- How to do -->
<int-xml:validating-filter xml-validator="xmlValidator"
schema-type="xml-schema"
throw-exception-on-rejection="true" />
<int:service-activator id="schematronValidationActivator" ref="schematronValidator" method="validate" />
</int:chain>
<bean id="xmlValidator" class="abc.validator.DomSourceValidator" />
Here is my Validator class defined:
import org.springframework.xml.validation.ValidationErrorHandler;
import org.springframework.xml.validation.XmlValidator;
import org.xml.sax.SAXParseException;
public class DomSourceValidator implements XmlValidator {
#Override
public SAXParseException[] validate(Source source) throws IOException {
/* How to implement this method?
Using XPath I can identify the root node from 'source' and then load
the appropriate XSD file. But don't know how to proceed
or what should be 'return'(ed) from here.
Any example is much appreciated.
*/
return null;
}
#Override
public SAXParseException[] validate(Source source, ValidationErrorHandler errorHandler) throws IOException {
// TODO Auto-generated method stub
return null;
}
}
Which is the best way of implementing the XML validator using Spring Integration?
There have been no changes since that comment.
As I said there, your validator needs to use XmlValidatorFactory to create a validator for each schema; then call a specific validator for each message; something like:
String schema = determineSchema(source);
XmlValidator val = lookupValidatorForSchema(schema);
if (val == null) {
// create a new one and add it to the map.
}
return val.validate(source);
If it helps other folks who are trying to do the same
Based on Gary's suggestion, I have come out with an implementation of XmlValidator by dynamically identifying input XML and then selecting appropriate Schema file to apply the validation.
Below is my spring integration configuration:
<int:gateway id="applicationServiceGateway" service-interface="abc.IGateway" default-request-channel="applicationRequestChannel" default-reply-channel="applicationResponseChannel" error-channel="errorProcessingChannel" />
<int:chain id="serviceRequestValidation" input-channel="applicationRequestChannel" output-channel="responseChannel">
<int-xml:validating-filter xml-validator="xmlValidator"
schema-type="xml-schema"
throw-exception-on-rejection="true" /> <!-- a MessageRejectedException is thrown in case validation fails -->
<int:service-activator id="schematronValidationActivator" ref="schematronValidator" method="validate" />
</int:chain>
<bean id="xmlValidator" class="abc.validator.DomSourceValidator">
<constructor-arg>
<map key-type="java.lang.String" value-type="java.lang.String">
<entry key="OTA_AirAvailRQ" value="common/schemas/FS_OTA_AirAvailRQ.xsd" />
<entry key="OTA_AirBookModifyRQ" value="common/schemas/FS_OTA_AirBookModifyRQ.xsd" />
<entry key="OTA_AirBookRQ" value="common/schemas/FS_OTA_AirBookRQ.xsd" />
</map>
</constructor-arg>
</bean>
To demonstrate I have used the OTA schema files to construct a map as constructor-arg. The map key is the root node from the XML file from the gateway and value is the location of the xsd file; and form the key-value pair map.
Refer to the below implementation class how this map is being used to identify the input XML and apply the validation.
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.Assert;
import org.springframework.xml.validation.ValidationErrorHandler;
import org.springframework.xml.validation.XmlValidator;
import org.springframework.xml.validation.XmlValidatorFactory;
import org.xml.sax.SAXParseException;
public class DomSourceValidator implements XmlValidator {
private static final Log LOGGER = LogFactory.getLog(DomSourceValidator.class);
private Map<String, String> schemaMap;
private static Map<String, XmlValidator> validatorMap = new HashMap<>();
public DomSourceValidator(Map<String, String> schemaMap) {
this.schemaMap = schemaMap;
}
#PostConstruct
private void init() throws IOException {
LOGGER.info("Constructing Validators from schema resource list ...");
Assert.notEmpty(schemaMap, "No schema resource map found");
if (validatorMap.isEmpty()) {
XmlValidator validator = null;
for (Map.Entry<String, String> entry : schemaMap.entrySet()) {
validator = createValidatorFromResourceUri(entry.getValue());
validatorMap.put(entry.getKey(), validator);
}
}
}
#Override
public SAXParseException[] validate(Source source) throws IOException {
Assert.notNull(schemaMap, "No validator(s) defined");
XmlValidator validator = lookupValidator(source);
return validator.validate(source);
}
#Override
public SAXParseException[] validate(Source source, ValidationErrorHandler errorHandler) throws IOException {
// Skip implementation
return null;
}
private XmlValidator lookupValidator(Source source) {
String reqType = determineRequestType(source);
LOGGER.info("Loading validator for type: " + reqType);
XmlValidator xmlValidator = validatorMap.get(reqType);
Assert.notNull(xmlValidator, "No validator found for type: " + reqType);
return xmlValidator;
}
private String determineRequestType(Source source) {
if (source instanceof DOMSource) {
return ((DOMSource) source).getNode().getFirstChild().getNodeName();
}
return null;
}
private XmlValidator createValidatorFromResourceUri(String schemaResource) throws IOException {
Assert.notNull(schemaResource);
return XmlValidatorFactory.createValidator(new ClassPathResource(schemaResource), XmlValidatorFactory.SCHEMA_W3C_XML);
}
}
As soon as the spring bean id="xmlValidator" is initialized, the #PostConstruct kicks in to create Validator instances using XmlValidatorFactory from the resource URIs to have a pre-initialized validators.
If there is a validation error, a org.springframework.integration.MessageRejectedException: Message was rejected due to XML Validation errors is thrown (ref. throw-exception-on-rejection="true" in the <int-xml:validating-filter />).
The above implementation works perfectly fine for me. One can customize it further, or post another version to achieve the same.
Note
Instead of using a <int-xml:validating-filter />, one can also use a <int:service-activator /> in the <int-chain />, as logically <int-xml:validating-filter /> does not actually do any filter logic. But it serves the purpose.

PrimeFaces Wizard is not reset

We are using the PrimeFaces 4.0 + spring 4 on Tomcat 7.
I go to PrimeFaces show case, open the wizard, type first name and last name hit the next button. Then I select other menus from left panel ( like AutoComplete ) I go back to wizard the first name and last name fields are clear. That is what I expected.
I developed a wizard same as above but every time I come back to wizard page the wizard still holds the previously entered value and is not reset.
My managed bean is as below ( I have used ViewScoped no SessionScope which mentioned in documents):
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#Named
#ViewScoped
public class AccountController {
#Valid
private Account account = new Account()
//Setters and getters
}
Edited:
I found that the problem is for integration of JSF and Spring. When I remove the #Named and use #ManagedBean it works fine. Any comments?!
Spring does not have a built in support for JSF ViewScope, but you can add this scope to JSF as:
public class ViewScope implements Scope {
public Object get(String name, ObjectFactory<?> objectFactory) {
Map<String, Object> viewMap = FacesContext.getCurrentInstance()
.getViewRoot().getViewMap();
if (viewMap.containsKey(name)) {
return viewMap.get(name);
} else {
Object object = objectFactory.getObject();
viewMap.put(name, object);
return object;
}
}
public Object remove(String name) {
return FacesContext.getCurrentInstance().getViewRoot().getViewMap()
.remove(name);
}
public String getConversationId() {
return null;
}
public void registerDestructionCallback(String name, Runnable callback) {
// Not supported
}
public Object resolveContextualObject(String key) {
return null;
}
}
Please refer to http://blog.primefaces.org/?p=702
And in your applicationConetext.xml
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="view">
<bean class="utils.ViewScope" />
</entry>
</map>
</property>
</bean>
And finally:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#Named
#ViewScoped
#Scope("view")
public class AccountController {
#Valid
private Account account = new Account()
//Setters and getters
}

JAX WS, JAXB and Null elements with attributes

I am trying to consume a web service using JAXWS and wsimport. The WSIMPORT tool generated all the required classes and I can invoke the service without any issues.
However, I noticed in cases where response contains a nil element with valid attribute values, JAXWS fails to unmarshall it and throws a NullPointerException. I used SOAP UI to help debug and here's what I found. The response returns the following XML (Excerpt):
<externalIdentifiers>
<identifierType code="2" name="Passport" xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
<identifierValue/>
<issuingCountry xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</externalIdentifiers>
In my Java code, when trying to read the "name" property of identifier type as above, it throws a NPE:
if(id.getIdentifierType() == null)
{
System.out.println("NULL");
}
System.out.println("Identifier Type: " + id.getIdentifierType().getName());
Output:
NULL
Exception in thread "main" java.lang.NullPointerException
To me that does looks a reasonable response as in the response, identifierType is set as xsi:nil="true". That is also perfectly valid XML as per W3C. Question is, how do I read the attribute values such as code and name in such a case?
Below is how you can support this use case:
Java Model
ExternalIdentifiers
You can change the identifierType property to be of type JAXBElement<IdentifierType> instead of IdentifierType. To do this you will need to annotate the property with #XmlElementRef.
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class ExternalIdentifiers {
#XmlElementRef(name="identifierType")
private JAXBElement<IdentifierType> identifierType;
public JAXBElement<IdentifierType> getIdentifierType() {
return identifierType;
}
}
ObjectFactory
You will need a corresponding #XmlElementDecl annotation on a create method in a class annotated with #XmlRegistry.
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
#XmlRegistry
public class ObjectFactory {
#XmlElementDecl(name="identifierType")
public JAXBElement<IdentifierType> createIdentifierType(IdentifierType identifierType) {
return new JAXBElement(new QName("identifierType"), IdentifierType.class, identifierType);
}
}
Demo Code
input.xml
<?xml version="1.0" encoding="UTF-8"?>
<externalIdentifiers>
<identifierType code="2" name="Passport" xsi:nil="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</externalIdentifiers>
Demo
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(ExternalIdentifiers.class, ObjectFactory.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum18834036/input.xml");
ExternalIdentifiers externalIdentifiers = (ExternalIdentifiers) unmarshaller.unmarshal(xml);
System.out.println(externalIdentifiers.getIdentifierType().getValue().getName());
}
}
Output
Passport
Note
Currently there is a bug in EclipseLink JAXB (MOXy) regarding this use case:
http://bugs.eclipse.org/404944

How to override CustomerStateRequestProcessor in broadleaf

How can I ovveride CustomerStateRequestProcessor#resolveAuthenticatedCustomer function in broadleaf?
I tried this:-
#Component("blCustomerStateRequestProcessor")
public class MyCustomerStateRequestProcessor extends
CustomerStateRequestProcessor {
#Resource(name = "blCustomerService")
protected CustomerService customerService;
#Override
public Customer resolveAuthenticatedCustomer(Authentication authentication) {
if (authentication instanceof OpenIDAuthenticationToken) {
OpenIDAuthenticationToken openIDAuthenticationToken = (OpenIDAuthenticationToken) authentication;
if (openIDAuthenticationToken.isAuthenticated()) {
return (Customer) openIDAuthenticationToken.getPrincipal();
} else {
return null;
}
} else {
return super.resolveAuthenticatedCustomer(authentication);
}
}
}
Added context component scan :-
<context:component-scan base-package="org.broadleafcommerce.common.web.security,com.mycompany.web.request.processor" />
This resulted in :-
org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'blCustomerStateRequestProcessor' for bean class [org.broadleafcommerce.profile.web.core.security.CustomerStateRequestProcessor] conflicts with existing, non-compatible bean definition of same name and class [com.mycompany.web.request.processor.MyCustomerStateRequestProcessor]
I am trying to overrid resolveAuthenticatedCustomer method for OpenIdAuthenticationToken.
Thanks
Rather than use component-scanning to redefine the bean, remove that annotation and do it via XML instead.
So your class definition would change to:
public class MyCustomerStateRequestProcessor extends
CustomerStateRequestProcessor {
...
}
And then in any of your applicationContext.xml files (except for the servlet one) add this:
<bean id="blCustomerStateRequestProcessor" class="com.yourcompany.site.web.MyCustomerStateRequestProcessor" />
Note that this pattern is the same for overriding any Broadleaf-defined beans.

Resources