I am working on a project with Spring and EJB/Primefaces and I want to pass values from the spring context to a managed bean. I will demonstrate with a sample code to clarify further.
Let's say we have the following domain class (I keep it simple for better readability):
public class Store {
@JsonProperty("store_name")
private String storeName;
//constructors, getters and setters...
}
The reason of @JsonProperty is because I am getting this value from an other application that POSTs a Json to the following Controller:
@Controller
@RequestMapping("/store")
public class StoreController {
@Autowired
private Store store;
@RequestMapping(method = RequestMethod.POST)
public String getStoreResponse(@RequestBody String store) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
LOGGER.info("Store Before Post: " + store.getName());
store = mapper.readValue(request, Store.class);
LOGGER.info("Store After Post: " + store.getName());
return "store";
}
}
I have configured the store bean at a BeanConfig class:
@Configuration
public class BeanConfig {
@Bean(name = "store")
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Store store() {
Store store = new Store();
store.setName("Test Store Name");
return store;
}
}
This is my managed bean:
@ManagedBean
@SessionScoped
public class StoreView extends SpringBeanAutowiringSupport {
private static final Logger LOGGER = LoggerFactory.getLogger(Store.class);
//@ManagedProperty("#{store}")
@Autowired
private Store store;
public void test() {
LOGGER.info("TEST " + store.getName());
}
//getters and setters
}
finally my xhtml:
<h:panelGrid columns="3">
<p:outputLabel for="j_store" value="#{messages['storeview.name']}" />
<p:inputText id="j_store" value="#{storeView.store.name}" />
<p:message for="j_store" />
<h:panelGroup />
<p:commandButton value="#{messages['storeview.test']}" action="#{storeView.test}" update="@form" ajax="false" />
</h:panelGrid>
When I am posting sample data using postman, the first time, the logger outputs:
10:35:57,433 INFO [com.store.test.controllers.StoreController] (default task-2) Store Before Post: Test Store Name
10:35:57,488 INFO [com.store.test.controllers.StoreController] (default task-2) Store After Post: posted store name
and if I continue calling the controller I keep getting the "posted store name", so it has kept the value.
But when I am going to the store.xhtml and hit the test button to submit the form, it still has the value set in the bean configuration file ("Test Store Name") and from that point on it keeps the value that I submit in the inputText.
I suspect it has to do with Spring and Faces context, I do not know if what I want to do is possible. If it is, please point out what should I change to make it work, otherwise, please provide me with an alternative solution.
Thanks in advance.
You are mixing @Autowired
and @ManagedBean
annotations.
@Autowired
is managed by Spring while @ManagedBean
is managed by JSF.
That means that probably you will have 2 instances of Store, the one modified by controller is not the same instance used by the managed bean.
You should annotate as @ManagedProperty("#{store}")
your store attribute in managed bean and define getter and setter.
To get it to work you also must define spring Expression Language resolver in faces-config.xml
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
Since jsf session is different from mvc session, you also have to use singleton scope in the definition of Store object.
@Scope(value = "singleton"........