How to define templates for Spring Batch jobs? - spring

I'm using Spring Batch 2.1.5. I have many jobs that are very similar between each other and I'm looking for a way to have an smaller XML acting as a job template.
The things that are shared among jobs are readers, processors, writers and one tasklet. Also some of the parameters for each of these beans are the same. For instance they all use the same data source.
I thought about 4 approaches and 3 of them don't work...
1 - Using a postprocessor to add the common beans and attributes as default values is not possible, because the Spring Batch class JobParserJobFactoryBean is not a public class.
2 - To add an XML extension seems to be a wrong thing, because I'm not adding any custom tags to the XML file.
3 - Using a PropertyOverrideConfigurer I can put default values into properties, but I have to define those values for each bean. So I'll have many repeated values and I'll only move the problem to properties.
4 - Using some kind of custom factory bean. These seems to be the only choice, but I don't know exactly how to plug it into the existing code.
Did anybody try to do this? Can somebody give tips or recommend resources on how to do it?

Spring Batch provides the ability to define Abstract Jobs (and steps, etc.) to inherit from. Take a look at the reference manual for more information. Using this you should be able to accomplish exactly what you are looking for.

Related

Converting Java DSL to Spring XML equivalent

So this may be a more general question, but I feel it needs to be asked.
Time and time again I come across examples on Camel's documentation pages where I say "that's exactly what I want!... but it's in Java not Spring. How the heck do I convert it properly?"
So my question is: What is the rule of thumb for converting things?
Is there some conversion guide out there?
For example, I wanted to append a \n to the end of each line as the data comes through a socket into a file using the Netty4 component.
I see an example such as .transform().body(append("\n"))
How would I interpret that as Spring, to put in my Spring-based route?
Maybe this is just a thing that a person new to Camel struggles with and once you get the hang of it you can see the obvious answer. But I feel like I can't be the only one who's thinking this about the examples out there.
It seems like a lot of Java -> Spring conversion can be done in a 1 to 1 ratio, but that's not all the time.
Well, the mapping isn't straightforward and there isn't a 1-to-1 mapping available - generally, a Java DSL method invocation will in most cases translate to a tag in Spring XML DSL but the position of that tag is not always the same - in some cases Java DSL method invocation chains translate to tags being placed on the same level, sometimes (e.g. idempotent consumer) the chain translates to child tags of the first invocation.
I guess that the mapping was done this way because XML and Java are two very different languages and making the mapping 1-1 would have crippled the expressiveness of at least one, if not both, DSLs.
My advice would be to always import the XML schema and rely on your IDE's auto-completion and the documentations from the schema itself and Camel's online documentation.
You can run your camel context via mvn camel:run goal and then use a JMX client to connect to that process. There is an mbean in camel which provides a method called dumpRoutesAsXML or similar. Invoking that one will give u the xml equivalent of your context. But keep in mind that it only prints the routes and all stuff out of routes is discarded.
Hope that helps,
Lars

Using Page Objects vs Config Files in Selenium

I've been using Ruby Selenium-Webdriver for one of the automation scripts I'm developing and I'm being asked to use Page Objects, we use page objects a lot however for this application I am using CSV file instead, I have defined all the xpaths that I'm using in my application in a CSV file and I'm parsing that CSV file in my script to refer to those objects, I would like to know is there much of a difference in using a class for defining Page Objects or using a CSV file instead apart from performance concern? I believe using a CSV file will be an addon for us from configuration standpoint and will make it much easier to maintain, any suggestions on this?
Edit - In our use case, we're actually automating applications built on a cloud based tool, so basically all the applications share same design structure from HTML standpoint so we define xpath patterns in CSV and then we pass certain parameters to some custom methods that we've developed to generate xpath's automatically using the CSV instead of finding those manually as its overhead for us because we already know that all the applications will share similar xpath pattern for all elements.
Thanks
I think, POM is better than CSV approach. In POM, you put elements for a page in a separate class file. So, if any change is to make then it's easier to find where to change/maintain. Moreover, it won't get too messy as CSV file and you don't need to use extra utility function to parse those.
There is also a pageobjects gem that provides a set of libraries over and above webdriver/watir, simplifying the code.
Plus, why xpaths? Its one of the last recommended ways to identify an element.
As for the frameork aspect, csv should be more of a maintenance problem than PageObjects. Its the basic difference between text and code. You enforce Object oriented approach on your elements in PageObjects but that is not possible with csv.
In the best case scenario, you have created a column/separate sheets defining which page that element xpath belongs to. That sounds like an overhead. As your application / suite grows there can be thousands of elements. Imagine parsing/ manually updating a csv with that kind of data.
Instead in PageObjects, your elements will be restricted to the Page. Any changes to the app will also specify which elements may get impacted. Now, when define your element as an object in PageObject, rather than css, you also dont need to explicitly create your elements by reading the csv.
It completely depends on the application and the type of test you might perform.
Since it is an automated test script, you do not have to really worry about the performance of the script (it might take few more milli seconds to parse, which should be OK).
Maintaining all the elements identification properties & corresponding actions in a CSV file will make the maintenance easier and make the framework application independent which are nice. But maintaining your framework is bit difficult to make it more robust. Both approaches have its own pros and cons.
Refer to below posts [examples are in java - but you will get the idea]:
Keyword driven framework
Advanced Page Objects
Update:
If you like both, you can comeup with your implementation to easily integrate these too.
#ObjectRepository(src="/login.csv")
public class LoginPage{
private Map<String, WebElement> elements;
public void login(){
elements.get("username").sendKeys('');
elements.get("password").sendKeys('');
elements.get("signin").click();
}
}
Ie, define all the elements in a config file like csv/json etc. Let the page object refer to the class for the page elements. All the methods will be part of the page class.

Achieve Multi-tenancy with GATE

I am using GATE in one of my applications and I have few queries related to Multi-tenancy. My requirements are as given below.
I have the keywords set, specific for each user and depending on
which user is signed in, I need to initialise gazetteer with the
applicable set of keywords.
At a given time there could be multiple users logging into my
application and I want to make sure that the multi-tenancy
approach will not be inefficient.
I don't want to store the keywords for each user in the .lst
file(s) but store it on a DB (mongo) and inject only at the
runtime.
I searched the web for few samples and though I found some thoughts on working with Processing Resource, I have no idea how the performance will be affected.
Your help is much appreciated.
Thanks in advance,
Sajith
That's an interesting use-case for a GATE gazetteer.
One thing I believe you should definitely do is add the user ID as a feature when you're creating the document. This way you'll be able to make your MongoDB query in a processing resource later on.
When you're processing the document, you have several options:
Create a custom PR which calls MongoDB and replicates the DefaultGazetteer code but with overwritten "init" method (or inherit or wrap it, haven't looked into much detail if that's possible). Instead of the default init method you should provide your list of keywords, then set the needed fields and call execute().
If you don't have too many keywords, create a custom PR (or groovy scripting PR) which calls MongoDB and does some simple regex search like the one in this thread.
They also suggest the stringsearch library in the comments. Then just use start and end indices to create Lookup annotations on your own.
You said you don't want that but still, several million words can be handled by both the default and the Hash gazetteer. Although, you should be careful as gate documents could be very memory-intensive if you have too many annotations - in your case Lookups for all user keywords.
Hope this helps.

Yaml properties as a Map in Spring Boot

We have a spring-boot project and are using application.yml files. This works exactly as described in the spring-boot documentation. spring-boot automatically looks in several locations for the files, and obeys any environment overrides we use for the location of those files.
Now we want to also expose those yaml properties as a Map. According to the documentation this can be done with YamlMapFactoryBean. However YamlMapFactoryBean wants me to specify which yaml files to use via the resources property. I want it to use the same yaml files and processing hierarchy that it used when creating properties, so that I can take still take advantage of "magical" features such as placeholder resolution in property values.
I didn't see any documentation on if this was possible.
I was thinking of writing a MapFactoryBean that looked at the environment and simply reversed the "flattening" performed by the YamlProcessor when creating the properties representation of the file.
Any other ideas?
The ConfigFileApplicationContextListener contains the logic for searching for files in various locations. And PropertySourcesLoader loads a file (Resource) into property sources. Neither is really designed for standalone use, but you could easily duplicate them if you want more control. The PropertySourcesLoader delegates to a collection of PropertySourceLoaders so you could add one of the latter that delegates to your YamlMapFactoryBean.
A slightly awkward but workable solution would be to use the existing machinery to collect the YAML on startup. Add a new PropertySourceLoader to your META-INF/spring.factories and let it create new property sources, then post process the Environment to extract the source map(s).
Beware, though: creating a single Map from multiple YAML files, or even a single one with multiple documents (let alone multiple files with multiple documents) isn't as easy as you might think. You have a map-merge problem, and someone is going to have to define the algorithm. The flattening done in YamlMapPropertiesBean and the merge in YamlMapFactoryBean are just two choices out of (probably) a larger set of possibilities.

How best to modify my model in Spring MVC if I care about IOC

I am building an application using Spring MVC. I want to make certain changes to my Model for every Controller in the application. In particular, I want to insert certain extra data into the model which will be present for all pages of the application.
I could do this several ways: just add the data at the end of every Controller, use a subclass of Model that adds my extra data, use a subclass of ModelAndView that wraps my Model, use a subclass of VelocityView that wraps the Model before using it... I'm sure there are other options.
But I have an "elegance" constraint: I don't want to write code in each and every Controller, I want this behavior defined in one-and-only-one place. Ideally, it would be controlled by my IOC bean config file.
Does anyone have a recommendation of how to achieve this elegantly?
Aspects are a good approach, but Spring MVC makes it even easier -- you can define a HandlerInterceptor that will be called before or after every time a request is handled. In the HandlerInterceptor postHandle method (in your class that implements the HandlerInterceptor interface) you can add your data to the ModelAndView. You define which handlers should be intercepted in your config file.
You could take a look at using Aspects. Spring even has an AOP extension that you could use.
In brief an aspect would allow you to define code once that would then get "woven" into your classes either when you compile the classes or when they are loaded by the classloader. It's relatively advanced stuff and isn't the most intuitive thing for new programmers to pick up, but it's intended to solve exactly the problem you're referring to.
I might be wrong, but I suspect that you may have described your requirements incorrectly.
You seem to be saying 'I want certain data to be added to my model, for all controllers'.
I suspect that you mean 'I want certain data to be available for all views'.
If my suspicions are correct, then adding the data to you model is polluting your model and violating the single responsibility principle. This is especially true if the same data is to be added to several models. Be careful that you are not just using your model as a convenient 'carrier' of the data - where the data doesn't really have anything to do with the model.
Admittedly, I'm not completely familiar with the Spring MVC way of doing things, but a more detailed example of what you're trying to achieve may allow for a more informed discussion.

Resources