Using SkipListener which implements Ordered with scope="step": No context holder available for step scope - listener

When using a skipListener with scope="step" which implements Ordered I get the following exception:
Error creating bean with name 'scopedTarget.scopedTarget.fisalisBatchMeldungenListener': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope
If I don't let my listener implement Ordered the exception does not ocure.
Here is my Bean Definition:
<bean id="erzeuger" class="...." scope="step">
<property name="user" ref="user" />
<property name="termin" ref="termin" />
<property name="services" ref="services"
</bean>
<bean id="listener" class="Listenerclass" scope="step">
<property name="erzeuger" ref="erzeuger" />
</bean>
And here is the part where I am using it:
<step id="myStep" parent="abstractBatchStep" xmlns="http://www.springframework.org/schema/batch">
<listeners merge="true">
<listener ref="listener" />
</listeners>
</step>
Has anyone an idea where the problem is?

I have the point:
When the Listener is added to the step, the step checks, if its implements Ordered. If it does, the step adds the listener to a collection which will be immediatly sort by using a comperator. This comperator invokes getOrder(9 on the instance of the listener. But if the listener ist stepScoped, the SpringBatch Factory (s. comment below) has to return the "real" bean instance. But at this point the "real" bean instance does not exist.
For sope="step" read this:
Scoped bean works in different manner. When context is created this bean is wrapped into additional proxy object (by default created by CGLIB), which is passed to the bean that refers it (this proxy is by default singleton, e.g. shared). So each time the method is invoked on the proxy in runtime Spring intersects the call, requests the factory to return the instance of the bean and invokes the method on that bean. The factory in its turn may lookup for "real" bean instance e.g. in HTTP request ("request" scope) or HTTP session ("session" scope) and/or create new instance if necessary. Late instantiation allows to initialize the scoped bean with "runtime" (scope) values, e.g. values from HTTP request/session which are obviously undefined when context was created. In particular "step"-scoped beans are bound to thread local (remember that steps are run in parallel for partitioning). So, scoped beans are dereferred when you call a method on them. Finally one can easily break this elegant Spring "ideology" by calling any method on scoped bean just after it is set to another bean (e.g. in the setter) :)

Related

Why the Exception raised from my Interceptor is not caught by <global-exception-mappings>?

I have a custom Interceptor, from which I throw an Exception;
The Action(s) running that Interceptor is managed by Convention plugin;
The Exception raised by the Interceptor is globally defined in struts.xml for the package the Action is running into.
RESULT: the exception mapping is ignored and I get the
Struts Problem Report
Struts has detected an unhandled exception:
...
Stacktraces
java.lang.IllegalArgumentException: my message
I guess I'm just missing something stupid... we've already discussed of this in a similar question, but it's still not clear if it can or can't work this way:
struts.xml
<package name="my-package" namespace="my" extends="struts-default">
<interceptors>
<interceptor name="myInterceptor" class="foo.bar.MyInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="myInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"/>
<global-results>
<result name="input">/WEB-INF/content/my-input.jsp</result>
<result name="error">/WEB-INF/content/my-error.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.IllegalArgumentException"
result="error" />
<exception-mapping exception="java.lang.Exception" result="error" />
</global-exception-mappings>
</package>
Action
#ParentPackage("my-package")
#Namespace("/my/blabla/yadayada")
public class MyAction extends MyBaseAction {
}
Interceptor
#Override
public String intercept(ActionInvocation actionInvocation) throws Exception {
// ....
if (somethingWrong) {
throw new IllegalArgumentException("All work and no play makes Jack a dull boy");
}
}
I've also tried defining global result / global exception mapping in the abstract BaseAction, or in the physical real Action itself, but they're ignored too.
Any idea on what to add / remove / change in order to make it work as it should ? This is not esoteric stuff, this is basic :|
The main candidate for exception mapping feature is actions throwing an exceptions.
Docs:
Exception mappings is a powerful feature for dealing with an Action class that throws an Exception. The core idea is that an Exception thrown during the Action method can be automatically caught and mapped to a predefined Result.
But exceptions thrown from interceptors can be also handled by exception interceptor. In order to catch other interceptors exceptions exception interceptor should be defined as the first interceptor in the stack.
From the ExceptionMappingInterceptor javadoc:
It is recommended that you make this interceptor the first interceptor on the stack, ensuring that it has full access to catch any exception, even those caused by other interceptors.

NoSuchBeanDefinitionException since Spring 3.1.3

I played around with the Spring version in my application today. I started out at Spring 3.1.1 and when I moved to Spring 3.1.3 my application began throwing a NoSuchBeanDefinitionException during startup.
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
matching bean of type
[nl.my.product.properties.Properties] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations: {}
I configured the Properties bean in the application context like this:
<!-- Gather properties from environment.properties in a map -->
<bean id="systemProperties" class="nl.my.product.properties.Properties">
<property name="propertyMap">
<map>
<entry key="email.from.address" value="${email.from.address}"/>
<entry key="site.host" value="${site.host}"/>
<entry key="site.protocol" value="${site.protocol}"/>
...
</map>
</property>
</bean>
And I autowired the bean into many of my controllers and services, like this:
#Autowired
public ArticleController(ArticleService articleService, PageBlockService pageBlockService, Properties systemProperties) {
this.articleService = articleService;
this.pageBlockService = pageBlockService;
this.properties = systemProperties;
}
Any clue as to why Spring is unable to find my bean since Spring 3.1.3? I tried moving the Properties bean to a package to was not also scanned for components, but that doesn't solve the problem.
When I annotate the Properties bean with #Component Spring does pick it up, but then the properties map is empty.
It started working when I removed the id="systemProperties" from the bean definition

jsf execute action on some input, switch page and bean management [duplicate]

I noticed that there are different bean scopes like:
#RequestScoped
#ViewScoped
#FlowScoped
#SessionScoped
#ApplicationScoped
What is the purpose of each? How do I choose a proper scope for my bean?
Introduction
It represents the scope (the lifetime) of the bean. This is easier to understand if you are familiar with "under the covers" working of a basic servlet web application: How do servlets work? Instantiation, sessions, shared variables and multithreading.
#Request/View/Flow/Session/ApplicationScoped
A #RequestScoped bean lives as long as a single HTTP request-response cycle (note that an Ajax request counts as a single HTTP request too). A #ViewScoped bean lives as long as you're interacting with the same JSF view by postbacks which call action methods returning null/void without any navigation/redirect. A #FlowScoped bean lives as long as you're navigating through the specified collection of views registered in the flow configuration file. A #SessionScoped bean lives as long as the established HTTP session. An #ApplicationScoped bean lives as long as the web application runs. Note that the CDI #Model is basically a stereotype for #Named #RequestScoped, so same rules apply.
Which scope to choose depends solely on the data (the state) the bean holds and represents. Use #RequestScoped for simple and non-ajax forms/presentations. Use #ViewScoped for rich ajax-enabled dynamic views (ajaxbased validation, rendering, dialogs, etc). Use #FlowScoped for the "wizard" ("questionnaire") pattern of collecting input data spread over multiple pages. Use #SessionScoped for client specific data, such as the logged-in user and user preferences (language, etc). Use #ApplicationScoped for application wide data/constants, such as dropdown lists which are the same for everyone, or managed beans without any instance variables and having only methods.
Abusing an #ApplicationScoped bean for session/view/request scoped data would make it to be shared among all users, so anyone else can see each other's data which is just plain wrong. Abusing a #SessionScoped bean for view/request scoped data would make it to be shared among all tabs/windows in a single browser session, so the enduser may experience inconsitenties when interacting with every view after switching between tabs which is bad for user experience. Abusing a #RequestScoped bean for view scoped data would make view scoped data to be reinitialized to default on every single (ajax) postback, causing possibly non-working forms (see also points 4 and 5 here). Abusing a #ViewScoped bean for request, session or application scoped data, and abusing a #SessionScoped bean for application scoped data doesn't affect the client, but it unnecessarily occupies server memory and is plain inefficient.
Note that the scope should rather not be chosen based on performance implications, unless you really have a low memory footprint and want to go completely stateless; you'd need to use exclusively #RequestScoped beans and fiddle with request parameters to maintain the client's state. Also note that when you have a single JSF page with differently scoped data, then it's perfectly valid to put them in separate backing beans in a scope matching the data's scope. The beans can just access each other via #ManagedProperty in case of JSF managed beans or #Inject in case of CDI managed beans.
See also:
Difference between View and Request scope in managed beans
Advantages of using JSF Faces Flow instead of the normal navigation system
Communication in JSF2 - Managed bean scopes
#CustomScoped/NoneScoped/Dependent
It's not mentioned in your question, but (legacy) JSF also supports #CustomScoped and #NoneScoped, which are rarely used in real world. The #CustomScoped must refer a custom Map<K, Bean> implementation in some broader scope which has overridden Map#put() and/or Map#get() in order to have more fine grained control over bean creation and/or destroy.
The JSF #NoneScoped and CDI #Dependent basically lives as long as a single EL-evaluation on the bean. Imagine a login form with two input fields referring a bean property and a command button referring a bean action, thus with in total three EL expressions, then effectively three instances will be created. One with the username set, one with the password set and one on which the action is invoked. You normally want to use this scope only on beans which should live as long as the bean where it's being injected. So if a #NoneScoped or #Dependent is injected in a #SessionScoped, then it will live as long as the #SessionScoped bean.
See also:
Expire specific managed bean instance after time interval
what is none scope bean and when to use it?
What is the default Managed Bean Scope in a JSF 2 application?
Flash scope
As last, JSF also supports the flash scope. It is backed by a short living cookie which is associated with a data entry in the session scope. Before the redirect, a cookie will be set on the HTTP response with a value which is uniquely associated with the data entry in the session scope. After the redirect, the presence of the flash scope cookie will be checked and the data entry associated with the cookie will be removed from the session scope and be put in the request scope of the redirected request. Finally the cookie will be removed from the HTTP response. This way the redirected request has access to request scoped data which was been prepared in the initial request.
This is actually not available as a managed bean scope, i.e. there's no such thing as #FlashScoped. The flash scope is only available as a map via ExternalContext#getFlash() in managed beans and #{flash} in EL.
See also:
How to show faces message in the redirected page
Pass an object between #ViewScoped beans without using GET params
CDI missing #ViewScoped and #FlashScoped
Since JSF 2.3 all the bean scopes defined in package javax.faces.bean package have been deprecated to align the scopes with CDI. Moreover they're only applicable if your bean is using #ManagedBean annotation. If you are using JSF versions below 2.3 refer to the legacy answer at the end.
From JSF 2.3 here are scopes that can be used on JSF Backing Beans:
1. #javax.enterprise.context.ApplicationScoped: The application scope persists for the entire duration of the web application. That scope is shared among all requests and all sessions. This is useful when you have data for whole application.
2. #javax.enterprise.context.SessionScoped: The session scope persists from the time that a session is established until session termination. The session context is shared between all requests that occur in the same HTTP session. This is useful when you wont to save data for a specific client for a particular session.
3. #javax.enterprise.context.ConversationScoped: The conversation scope persists as log as the bean lives. The scope provides 2 methods: Conversation.begin() and Conversation.end(). These methods should called explicitly, either to start or end the life of a bean.
4. #javax.enterprise.context.RequestScoped: The request scope is short-lived. It starts when an HTTP request is submitted and ends after the response is sent back to the client. If you place a managed bean into request scope, a new instance is created with each request. It is worth considering request scope if you are concerned about the cost of session scope storage.
5. #javax.faces.flow.FlowScoped: The Flow scope persists as long as the Flow lives. A flow may be defined as a contained set of pages (or views) that define a unit of work. Flow scoped been is active as long as user navigates with in the Flow.
6. #javax.faces.view.ViewScoped: A bean in view scope persists while the same JSF page is redisplayed. As soon as the user navigates to a different page, the bean goes out of scope.
The following legacy answer applies JSF version before 2.3
As of JSF 2.x there are 4 Bean Scopes:
#SessionScoped
#RequestScoped
#ApplicationScoped
#ViewScoped
Session Scope: The session scope persists from the time that a session is established until session termination. A session terminates
if the web application invokes the invalidate method on the
HttpSession object, or if it times out.
RequestScope: The request scope is short-lived. It starts when an HTTP request is submitted and ends after the response is sent back
to the client. If you place a managed bean into request scope, a new
instance is created with each request. It is worth considering request
scope if you are concerned about the cost of session scope storage.
ApplicationScope: The application scope persists for the entire duration of the web application. That scope is shared among all
requests and all sessions. You place managed beans into the
application scope if a single bean should be shared among all
instances of a web application. The bean is constructed when it is
first requested by any user of the application, and it stays alive
until the web application is removed from the application server.
ViewScope: View scope was added in JSF 2.0. A bean in view scope persists while the same JSF page is redisplayed. (The JSF
specification uses the term view for a JSF page.) As soon as the user
navigates to a different page, the bean goes out of scope.
Choose the scope you based on your requirement.
Source: Core Java Server Faces 3rd Edition by David Geary & Cay Horstmann [Page no. 51 - 54]

Use Variable Substitution for Logback Appender Class Attribute

Is it possible to use variable substitution when specifying the implementing class for a Logback appender? e.g.,
<appender name="LOGFILE" class="${LOGFILE_APPENDER_CLASS}">
When specified as above, Logback appears to attempt to load a class with a name of "${LOGFILE_APPENDER_CLASS}". i.e., no variable substitution is performed!
21:17:11,331 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [${LOGFILE_APPENDER_CLASS}]
21:17:11,333 |-ERROR in ch.qos.logback.core.joran.action.AppenderAction - Could not create an Appender of type [${LOGFILE_APPENDER_CLASS}]. ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type ${LOGFILE_APPENDER_CLASS}
at ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type ${LOGFILE_APPENDER_CLASS}
I want to send output to a file in production and console for eclipse developers. I don't want to duplicate the appender configuration if possible as it contains a long list of filters that will be the same in most cases.
As per the question, all evidence indicates that LogBack will not perform variable substitution in this scenario.
Adopted solution was to switch from XML configuration file to Groovy configuration file. Then dynamically control the list of appenders based on a "bDeveloper" variable derived from the environment.
def bDeveloper = ["","true"].contains("${System.getProperty("developer")}".toLowerCase())
if (bDeveloper) {
scan("15 seconds")
lstRootAppenders.add("BEAGLE")
oLogfileAppender = ch.qos.logback.core.ConsoleAppender
}

Configure windsor interceptor to hook only marked methods

Is there possibility to configure Interceptor to hook methods only of special interface, or by base class?
Currently I have registered Interceptor that works with scope of connections to one DB. Now I added another scope working with another db and want to add another interceptor, which will hook methods of second scope. It is possible to configure interceptor via xml files, instead of checking target of invocation properties.
I've added interceptor via components:
<component
type="Common.IoC.SessionScopeInterceptor, Common"
lifestyle="transient">
</component>
AFAIK this interceptor intercepts all methods of all classes registered in windsor container.
I wand to add something like this^
<component
type="Common.IoC.SessionScopeInterceptor, Common"
lifestyle="transient"
interceptOnlyVirtualMethods="true"
interceptClass="Common.IoC.SessionScope1, Common"
>
</component>
you need to create your own AbstractFacility that implements your desired behaviour. Essentially, you need to implement something similar to what Mikael Sundberg did in the answer to this question.