I have a Spring 3.2.11 and Webflow 2.4.0 app using JSF2 for view rendering.
One of my pages uses a view-state model bean for validation but when the validatePasswordChange method is called, the bean properties have not been autowired so I get a NPE. I don't understand why they're null!?
Thank you for any suggestions.
Here's my bean validation method. Why is the passwordService property null?
public void validatePasswordChange(ValidationContext context) {
MessageContext messages = context.getMessageContext();
if (!confirmPassword.equals(newPassword)) {
messages.addMessage(new MessageBuilder().error()
.source("confirmPassword")
.defaultText(
this.getMessage("kyn.password.change.validation.noMatch"))
.build());
};
List<String> validationMessages = passwordService
.validatePasswordPolicyCompliance(getUsername(),
newPassword);
if (validationMessages != null) {
for (String message : validationMessages) {
messages.addMessage(new MessageBuilder().error()
.source("confirmPassword")
.defaultText(message).build());
}
}
}
Here's a snippet from my flow.xml. I'm inserting passwordUpdateBean into the flowScope in the on-start and expecting the model attribute to use it:
<on-start>
<evaluate expression="passwordUpdateBean" result="flowScope.passwordUpdateBean"></evaluate>
</on-start>
<view-state id="passwordChange" model="passwordUpdateBean">
<transition on="proceed" to="update"/>
<transition on="cancel" to="redirectCancel" validate="false"/>
</view-state>
And here's my bean config xml:
<bean id="passwordUpdateBean"
class="com.xyz.PasswordUpdateBean"
scope="prototype"
parent="abstractWebBean">
<property name="passwordService" ref="passwordManagementService"/>
<property name="appUserDetailsService" ref="appUserDetailsService"/>
<property name="autoLoginAfterEnrollment" value="true"/>
<property name="usernamePasswordAuthenticationProvider" ref="usernamePasswordAuthenticationProvider"/>
</bean>
beans will NOT auto wire inside your flow definitions. You have get have to explicitly retrieve the bean into the flow definition.
Note #Service class annotations are automatically accessible in flow files (i.e <evaluate expression="myService.getPasswordUpdateBean()" result="flowScope.passwordUpdateBean"/>)
<on-start>
<evaluate expression="....getPasswordUpdateBean()" result="flowScope.passwordUpdateBean"></evaluate>
<!-- where '....' = either #service class or some other obj that holds a reference to the bean you seek -->
</on-start>
Related
I am trying to use ftp-inbound-adapter to poll files based on the the current date.And my inbound adapter uses a filter which refers to bean myfilter .The problem here is the current date is initailized at the startup and is not been processed dynamically..I would like to get the current date for every new message
<int-ftp:inbound-channel-adapter id="ftpInbound"
channel="ftpChannel"
session-factory="ftpsClientFactory"
filter="myFilter"
</int-ftp:inbound-channel-adapter>
<bean id="myFilter" class="org.springframework.integration.ftp.filters.FtpRegexPatternFileListFilter" scope="prototype">
<constructor-arg value="#{T(java.time.LocalDateTime).now().format(T(java.time.format.DateTimeFormatter).ofPattern('MMddyy'))}.(xls|xlsx)"/>
<aop:scoped-proxy/>
</bean>
UPDATE
I changed from this
<bean id="currentDate" class="java.util.Date" factory-bean="fastDateFormat"
scope="prototype" factory-method="format" >
<aop:scoped-proxy/>
<constructor-arg>
<bean class="java.util.Date" />
</constructor-arg>
</bean>
<bean id="myFilter" class="org.springframework.integration.ftp.filters.FtpRegexPatternFileListFilter" scope="prototype">
<constructor-arg value="#{currentDate}.(xls|xlsx)"/>
</bean>
And my inbound adapter uses a filter which refers to bean myFilter .. The problem here is the current date is initailized at the startup and is not been processed dynamically..I would like to get the current date for every new message
This impossible with your current configuration because that filter is just a singleton bean created only once at start up pulling that your currentDate for injection only once as well.
You may try to add <aop:scoped-proxy/> into your currentDate bean definition, though: https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#beans-factory-scopes-other-injection, but I would suggest to inject BeanFactorty into your filter and call getBean("currentDate", Date.class) every time you need a new instance of that prototype.
UPDATE
You inject BeanFactory into your filter instead of that currentDate bean. And then when filter logic is called you do Date currentDate = this.beanFactory.getBean("currentDate", Date.class);.
UPDATE2
Here is what I think should work for you:
public class DynamicRegexPatternFilter extends AbstractFileListFilter<File> {
#Autowired
private BeanFactory beanFactory;
#Override
public boolean accept(File file) {
return Pattern.compile(this.beanFactory.getBean("currentDate", String.class) + ".(xls|xlsx)")
.matcher(file.getName())
.matches();
}
}
You can make custom filter. Implement FileListFilter and override filterFiles method which takes input argument as array of LsEntry. LsEntry is nothing but a small metadata object of a File present at (S)FTP. It comprises of File Name and the date on which it was modified.
#Override
public List<LsEntry> filterFiles(LsEntry[] files) {
List<LsEntry> result = new ArrayList<LsEntry>();
Vector<LsEntry> list = new Vector<LsEntry>();
Collections.addAll(list, files);
ChannelSftp.LsEntry lastModifiedEntry = Collections.max(list,
(Comparator.comparingInt(entry -> entry.getAttrs().getMTime())));
result.add(lastModifiedEntry);
return result;
}
Reference: https://stackoverflow.com/a/60635859/11325128
How to notify with a listener when the Future method has finished using #Async annotation in spring based service layer and with a thread pool in application context called from a ManagedBean . I have tried with p:poll listener with a listener method future.isDone() but is not very effective because it makes many requests to the server.
Edit.
here is the example
#ManagedBean
#ViewScoped
public class Controller
{
Future<SomeModel> someFuture;
#ManagedProperty(value = "#{someService}")
private SomeService someService;
private String things;
private SomeModel someModel;
private boolean renderSomeModel;
public void callAsyncMethod()
{
someFuture = someService.thingsToBeInsered(things);
//here make the poll in jsf start
}
public void methodAsyncFinished{
if(someFuture!=null)
{
if(this.someFuture.isDone())
{
renderSomeModel = true;
//here make the poll to stop
}
}
}
#Service
public class SomeService
{
#Async
Future<SomeModel> thingsToBeInsered(things)
{
//Calling the dao here
return new AsyncResult<SomeModel>(things);
}
}
//spring context
<task:annotation-driven executor="taskExecutor" proxy-target-class="true"/>
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="${thread_pool.corePoolSize}" />
<property name="maxPoolSize" value="${thread_pool.maxPoolSize}" />
<property name="WaitForTasksToCompleteOnShutdown" value="${thread_pool.waitForTasksToCompleteOnShutdown}" />
</bean>
jsf
<p:poll autoStart="false" widgetVar="asyncGenPoll" interval="6" listener="#{controller.methodAsyncFinished}" update="resultPanel"/>
We recently upgraded our spring version to 4.x from 2.x which started causing some issues with one of our 'threadpooltaskexecutor' implementation.
The implementation was as below:
public class A
{
..............................
..............................
public void create()
{
this.threadPoolTaskExecutor.execute(new Runnable()
{
public void run()
{
createABCAsync();
}
});
}
public void createABCAsync()
{
createABC();
}
public void createABC()
{
.....................................
.....................................
abcDAO.saveOrUpdate(abc);
xyzDAO.saveOrUpdate(xyz);
}
...................................................
...................................................
}
The bean definitions for class A has entries like below:
`<bean id="clsIntegrationManager" parent="txProxyTemplate"`>
.................................................
.................................................
<property name="transactionAttributes">
<props>
<prop key="create">PROPAGATION_REQUIRED</prop>
<prop key="createABCAsync">PROPAGATION_REQUIRES_NEW</prop>
</props>
</property>
After spring upgrade, the above code threw an exception as below:
Exception in thread "threadPoolTaskExecutor-1" org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
To resolve the above I added an entry like follows in the DAO layer bean definition file:
<bean id ="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="checkWriteOperations" value="false"/>
</bean>
The above entry resolved the exception, but the asynchronous method execution which starts a separate transaction using REQUIRES_NEW is not doing any database commits. We have a couple of 'saveOrUpdate()' calls inside the createABC() method but nothing gets saved in database.
Can someone please help in understanding what is going wrong above ?
I tried a few different solution approaches, one of which is described here: [Spring TaskExecutor Transaction Lost (Proxy vs. Direct call) but this did not help.
1) Is there a way to unmarshall MTOM message using Camel Spring-WS component?
2) I tried with Camel JAXB dataformat. It didn't work. Datahandler doesn't have any content. Does JAXB dataformat support MTOM?
<dataFormats>
<jaxb id="jaxb" contextPath="com.mycompany.hr.jaxb"/>
</dataFormats>
<route>
<from uri="spring-ws:rootqname:{http://mycompany.com/hr/schemas}HolidayRequest?endpointMapping=#endpointMapping" />
<unmarshal ref="jaxb"/>
<process ref="testProcessor" />
</route>
3) I thought MTOM is not enabled in JAXB dataformat. So I created a custom dataformat using MTOM enabled JAXB2Marshaller. But still facing the same issue.
import java.io.InputStream;
import java.io.OutputStream;
import javax.xml.transform.Source;
import org.apache.camel.Exchange;
import org.apache.camel.spi.DataFormat;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
public class MtomDataFormat implements DataFormat {
public void marshal(Exchange arg0, Object arg1, OutputStream arg2)
throws Exception {
// TODO Auto-generated method stub
}
public Object unmarshal(Exchange exchange, InputStream is) throws Exception {
Source source = exchange.getContext().getTypeConverter().mandatoryConvertTo(Source.class, is);
Jaxb2Marshaller mar = new Jaxb2Marshaller();
mar.setContextPath("com.mycompany.hr.jaxb");
mar.setMtomEnabled(true);
return mar.unmarshal(source);
}
}
Spring configuration
<bean id="endpointMapping"
class="org.apache.camel.component.spring.ws.bean.CamelEndpointMapping">
</bean>
<bean id="testProcessor" class="TestProcessor" />
<bean id="mtomDataFormat" class="MtomDataFormat" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="spring-ws:rootqname:{http://mycompany.com/hr/schemas}HolidayRequest?endpointMapping=#endpointMapping" />
<unmarshal ref="mtomDataFormat"/>
<process ref="testProcessor" />
</route>
</camelContext>
I am trying to serialize JAXB annotated class with Jackson using RESTEasy. By default ResteasyJacksonProvider is configured to use JACKSON annotation only. Is there a way to configure ResteasyJacksonProvider to use JAXB annotation using spring? There are couple of programmatic ways but would prefer if there is some spring configuration.
Couple of ways I am thinking of
Use ContextResolver for ObjectMapper type to return ObjectMapper configured to use JaxbAnnotationIntrospector instead of JacksonAnnotationIntrospector.
Extend ResteasyJacksonProvider and pass JAXB annotation during construction.
Any other way?
Well the first option of using ContextResolver works but I still think there should be an easier way to do this just by some configuration.
You can get this from the configuration only, no need to program anything special.
Here's how to:
First set your configuration right, I use Jackson + JAXB, both set under ContentNegotiatingViewResolver bean:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1"/>
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml" />
<entry key="json" value="application/json" />
</map>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller">
<oxm:jaxb2-marshaller id="marshaller">
<oxm:class-to-be-bound name="com.shay.dashboard.data.structure.page.PageObject" />
<oxm:class-to-be-bound name="com.shay.dashboard.data.structure.tab.TabObject" />
<oxm:class-to-be-bound name="com.shay.dashboard.data.structure.section.SectionObject" />
<oxm:class-to-be-bound name="com.shay.dashboard.data.structure.element.nonembedded.ElementObject"/>
<oxm:class-to-be-bound name="com.shay.dashboard.data.structure.element.embedded.EmbeddedElementObject"/>
<oxm:class-to-be-bound name="com.shay.dashboard.data.structure.chart.common.ChartManager"/>
</oxm:jaxb2-marshaller>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
</list>
</property>
</bean>
Notice that under the marshaller I set the oxm:class-to-be-bound - those are the classes to be bound by JAXB.
Now for the module, I used ordinary annotation package (javax.xml.bind.annotation), non marshaller specific. Jackson Json and JAXB both know how to read it.
For example:
#XmlAccessorType(XmlAccessType.NONE)
#XmlRootElement(name="page")
public class PageObject implements ComponentTypeObject{
#XmlAttribute(name="name")
private String name;
#XmlAttribute(name="id",required=true)
private String id;
#XmlElements({#XmlElement(name="tab", type=TabXmlAdapter.class)})
private List<TabXmlAdapter> tabRef;
Finally the controller for your MVC needs to return a model and view:
#RequestMapping(value="/get_page", method = RequestMethod.GET)
public ModelAndView initPage()
{
ModelAndView mav = null;
try
{
PageObject myPage = (PageObject) Utilities.getUtilities().loadObjectFromFile(XmlComponentType.page);
mav = new ModelAndView("page","page",myPage);
}
catch (Exception e)
{
e.getMessage();
}
return mav;
}
Now while calling your URL ending with .json you'd get the JSON representation, and with .xml - and XML. Both are translated by the viewer, provided you gave the correct mapping when annotating the module.