javax.el.ELException: Cannot convert Protocol#7ebc9002 of type class Protocol to class Protocol$$EnhancerByCGLIB$$22af7fa3 (lazy loadding) - spring

I struggle to make hibernate 3.1 lazy loading working with JSF 1.2
Caused by: javax.el.ELException: Cannot convert foo.bar.Protocol#7ebc9002 of type class foo.bar.Protocol to class foo.bar.Protocol$$EnhancerByCGLIB$$22af7fa3
at org.apache.el.lang.ELSupport.coerceToType(ELSupport.java:438)
at org.apache.el.ExpressionFactoryImpl.coerceToType(ExpressionFactoryImpl.java:46)
at com.sun.faces.renderkit.html_basic.RadioRenderer.renderOption(RadioRenderer.java:87)
at com.sun.faces.renderkit.html_basic.SelectManyCheckboxListRenderer.encodeEnd(SelectManyCheckboxListRenderer.java:146)
I read that hibernate will replace the lazy loading proxy on demand, but it seems to do not work on JSF converter call.
Note that Protocols are bound to radio buttons in the view
Do you know how to workaround this ? I can't find someone who have the same issue as me.
applicationContext :
<bean id="protocol" class="foo.bar.Protocol" abstract="false"
lazy-init="default" autowire="byName" dependency-check="default" scope="session">
<aop:scoped-proxy />
</bean>
<bean id="protocolConverter" class="foo.bar.ProtocolConverter" abstract="false"
lazy-init="default" autowire="byName" dependency-check="default" scope="singleton">
<property name="protocolDAO" ref="protocolDAO" />
</bean>
view :
<h:selectOneRadio value="#{pingControler.ping.protocol}" converter="#{protocolConverter}">
<f:selectItems value="#{pingControler.allProtocolsSelectItems}" />
<a4j:support event="onchange" reRender="foo1,foo2" />
</h:selectOneRadio>
ping :
public class Ping {
// Fields
private Integer pingId;
private Protocol protocol;
...
}
pingControler :
private Ping ping;
public void init(ActionEvent event) {
ping = new Ping();
}
public void save(ActionEvent event) throws Exception {
if (ping.getPingId() == null) {
pingPersistent.addPing(ping);
} else {
pingPersistent.updatePing(ping);
}
}

I figured out (finally) how to workaround this. I'm not sure if this is the proper way, but it works.
I added this code :
private static <T> T initializeAndUnproxy(T entity) {
if (entity == null) {
throw new NullPointerException("Entity passed for initialization is null");
}
Hibernate.initialize(entity);
if (entity instanceof HibernateProxy) {
entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
}
return entity;
}
And i called it in my Converter like this :
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String value) {
Protocol protocol = protocolDAO.findById(new Integer(value));
return initializeAndUnproxy(protocol);
}
instead of this :
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String value) {
return protocolDAO.findById(new Integer(value));
}
By the way, i did a mistake when i though that $$EnhancedByCGLIB$$ necessarily means an hibernate proxy. I read somewhere else that it's a library and could be used by Spring dependency injection too for example. Just to let you know.
I hope this will help the few jsf 1.2 / hibernate 3.1 users remaining. Should i upvote myself ?

Related

Spring webflow binder not binding collection object

I'm using spring webflow v2.4.8 in my app, and trying to bind the model properties using <binder></binder>. But my collection objects (list1, list2 both ArrayList) never get bound. If I remove the <binder></binder> altogether, all properties are getting correctly bound, but in my case that is not an option.
Do I need to use some custom converter here? Any help greatly appreciated
<view-state id="myId" model="myModel" view="myView" >
<binder>
<binding property="list1"/>
<binding property="list2"/>
<binding property="string1"/>
<binding property="string2"/>
.
.
.
</binder>
.
.
.
</view-state>
It's been a while, but in my project I have a custom ConversionService, so maybe you can try using one like this:
[EDIT]
Here is an example of a converter using a service (that gets the object from the db)
#Named
public class StringToMyType extends StringToObject {
#Inject
private MyTypeService service;
public StringToMyType(MyType myObject) {
super(myObject);
}
#Override
protected Object toObject(String id, Class<?> targetClass) throws Exception {
if (id != null && id.length != 0) {
return service.findById(new Long(id));
} else return null;
}
#Override
protected String toString(Object myObject) throws Exception {
return Objects.toString(((MyType) myObject).getId());
}
}
and add it here
public class CustomDefaultConversionService extends DefaultConversionService {
#Override
protected void addDefaultConverters() {
super.addDefaultConverters();
addConverter(new MyTypeConverter()
addConverter(new ObjectToCollection(this));
}
}
it needs to then be registered this way (xml):
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator" conversion-service="conversionService"/>
<bean id="conversionService" class="path.to.converter.CustomDefaultConversionService"/>
hope this helps

Bean property 'feedId' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

Below is code Batch snippet:
XML :
</beans:property> -->
<beans:bean id="RDFieldSetMapper" class="in.gov.tds.batch.mapper.RDFieldSetMapper"
autowire="byName" scope="step">
<!-- <beans:property name="feedId" value="429717"></beans:property> -->
<beans:property name="feedId" value="#{jobParameters[feedId]}"></beans:property>
</beans:bean>
setter method in Java Class:
recordDetail.setFeedId(new Long(feedId));
Please provide the resolution as I am getting Invalid setter method.
More Mapper detail:
public class RDFieldSetMapper implements FieldSetMapper {
private Long feedId;
private int batchCounter;
#Override
public RecordDetail mapFieldSet(FieldSet fieldSet) throws BindException {
if (LOGGER.isDebugEnabled())
LOGGER.debug("Record Detail Mapper:-- " + " " + fieldSet);
RecordDetail recordDetail = new RecordDetail();
// feedId = FeedReader.feedId;
recordDetail.setFeedId(new Long(feedId));
}
}
solved the problem. Issue : setter and getter methods are not present in the mapper class.
public Long getFeedId() {
return feedId;
}
public void setFeedId(Long feedId) {
this.feedId = feedId;
}

Populate spring servlet context on start up

It may be a duplicate question.
My question is: I want to read a property from properties file and put that in servlet context as soon as I start my application.
Could any one please help me on that?
Thanks in advance.
Implement Spring's ApplicationListener:
#Component
public class MyApplicationListener implements ApplicationListener {
/* if you want to set predefined properties you even don't have to load properties filed - you can directly inject properties values ... you can configure it in applicationContext.xml
<util:list id="locations">
<value>classpath:appconfig1.properties</value>
<value>classpath:appconfig2.properties</value>
</util:list>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:locations-ref="locations" />
*/
#Value("${myproperty1}") private String myProperty1;
#Value("${myproperty2}") private String myProperty2;
#Value("${myproperty3}") private String myProperty3;
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextClosedEvent) {
applicationClosed();
return;
}
if (!(event instanceof ContextRefreshedEvent)) return;
ContextRefreshedEvent e = (ContextRefreshedEvent) event;
ApplicationContext appContext = e.getApplicationContext();
if (!(appContext instanceof WebApplicationContext)) return;
WebApplicationContext ctx = (WebApplicationContext) e.getApplicationContext();
ServletContext context = ctx.getServletContext();
context.setAttribute("myProperty1", myProperty1);
context.setAttribute("myProperty2", myProperty2);
context.setAttribute("myProperty3", myProperty3);
}
}

Unable to move from controller to view in Spring MVC

I am using Spring MVC framework for my project.
I am unable to get my code running from controller to view.
Sharing the important chunk of code here.....
Inside AdminController.java controller
System.out.println("controller returning");
return new ModelAndView("dataFrame_","frameData",dataString);
Inside dispatcher-servlet.xml
<bean name="/dataFrame.htm"
class="com.organization.dept.spec.proj.module.controller.DataFrameController" >
</bean>
<bean id="dataFrameViewResolver"
class="com.organization.dept.spec.proj.module.view.DataFrameViewResolver">
<property name="dataFrameView">
<bean class="com.organization.dept.spec.proj.module.view.DataFrameView" />
</property>
<property name="dataFramePrefix" value="dataFrame_"></property>
</bean>
inside DataFrameViewResolver.java
public class DataFrameViewResolver extends AbstractCachingViewResolver {
private String dataFramePrefix;
private View dataFrameView;
#Override
protected View loadView (String viewName, Locale locale) throws Exception {
View view = null;
if(viewName.startsWith(this.dataFramePrefix)){
view = dataFrameView;
}
return view;
}
and
public String getDataFramePrefix() {
return dataFramePrefix;
}
public void setDataFramePrefix(String dataFramePrefix) {
this.dataFramePrefix = dataFramePrefix;
}
public View getDataFrameView() {
return dataFrameView;
}
public void setDataFrameView(View dataFrameView) {
this.dataFrameView = dataFrameView;
}
}
inside DataFrameView.java ...
public class DataFrameView extends AbstractView {
#Override
protected void renderMergedOutputModel(Map map, HttpServletRequest request,HttpServletResponse response) throws Exception {
System.out.println("RenderMergeoutputModel"); //line 99
I was unable to get the above system.out.println i.e. was unable to execute my code till that line 99.
The localhost log files of tomcat revealed some exception java.lang.ClassNotFoundException: javax.servlet.jsp.jstl.core.Config
I put the jstl-1.2.jar in lib and this could just get me rid of exception however still was unable get sysout of DataFrameView of line 99.

Custom property editors do not work for request parameters in Spring MVC?

I'm trying to create a multiaction web controller using Spring annotations. This controller will be responsible for adding and removing user profiles and preparing reference data for the jsp page.
#Controller
public class ManageProfilesController {
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(UserAccount.class,"account", new UserAccountPropertyEditor(userManager));
binder.registerCustomEditor(Profile.class, "profile", new ProfilePropertyEditor(profileManager));
logger.info("Editors registered");
}
#RequestMapping("remove")
public void up( #RequestParam("account") UserAccount account,
#RequestParam("profile") Profile profile) {
...
}
#RequestMapping("")
public ModelAndView defaultView(#RequestParam("account") UserAccount account) {
logger.info("Default view handling");
ModelAndView mav = new ModelAndView();
logger.info(account.getLogin());
mav.addObject("account", account);
mav.addObject("profiles", profileManager.getProfiles());
mav.setViewName(view);
return mav;
}
...
}
Here is the part of my webContext.xml file:
<context:component-scan base-package="ru.mirea.rea.webapp.controllers" />
<context:annotation-config/>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
...
/home/users/manageProfiles=users.manageProfilesController
</value>
</property>
</bean>
<bean id="users.manageProfilesController" class="ru.mirea.rea.webapp.controllers.users.ManageProfilesController">
<property name="view" value="home\users\manageProfiles"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
However, when i open the mapped url, i get exception:
java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [ru.mirea.rea.model.UserAccount]: no matching editors or conversion strategy found
I use spring 2.5.6 and plan to move to the Spring 3.0 in some not very distant future. However, according to this JIRA https://jira.springsource.org/browse/SPR-4182 it should be possible already in spring 2.5.1.
The debug shows that the InitBinder method is correctly called.
What am i doing wrong?
Update:
public class UserAccountPropertyEditor extends PropertyEditorSupport {
static Logger logger = Logger.getLogger(UserAccountPropertyEditor.class);
public UserAccountPropertyEditor(IUserDAO dbUserManager) {
this.dbUserManager = dbUserManager;
}
private IUserDAO dbUserManager;
public String getAsText() {
UserAccount obj = (UserAccount) getValue();
if (null==obj) {
return "";
} else {
return obj.getId().toString();
}
}
public void setAsText(final String value) {
try {
Long id = Long.parseLong(value);
UserAccount acct = dbUserManager.getUserAccountById(id);
if (null!=acct) {
super.setValue(acct);
} else {
logger.error("Binding error. Cannot find userAccount with id ["+value+"]");
throw new IllegalArgumentException("Binding error. Cannot find userAccount with id ["+value+"]");
}
} catch (NumberFormatException e) {
logger.error("Binding error. Invalid id: " + value);
throw new IllegalArgumentException("Binding error. Invalid id: " + value);
}
}
}
There are no errors logged from UserAccountPropertyEditor.
I don't think you want to be specifying the field argument to WebDataBinder.registerCustomEditor(). This intended to work alongside form-backing objects, and you're not using that.
Try the simpler 2-arg method instead, and it should work:
binder.registerCustomEditor(UserAccount.class, new UserAccountPropertyEditor(userManager));
binder.registerCustomEditor(Profile.class, new ProfilePropertyEditor(profileManager));

Resources