Possible to add more ItemWriters to ClassifierCompositeItemWriter at runtime - spring-batch

ClassifierCompositeItemWriter allows us to choose which ItemWriter to use at runtime based on the value of something. For example..
public class CustomerClassifier implements
Classifier<Customer, ItemWriter<Customer>> {
private ItemWriter<Customer> fileItemWriter;
private ItemWriter<Customer> jdbcItemWriter;
#Override
public ItemWriter<Customer> classify(Customer customer) {
if(customer.getState().matches("^[A-M].*")) {
return fileItemWriter;
} else {
return jdbcItemWriter;
}
}
public void setFileItemWriter(ItemWriter<Customer> fileItemWriter) {
this.fileItemWriter = fileItemWriter;
}
public void setJdbcItemWriter(ItemWriter<Customer> jdbcItemWriter) {
this.jdbcItemWriter = jdbcItemWriter;
}
}
The decision here on what ItemWriters are possible is all done at compile time.
Is it possible to add more ItemWriter at runtime?

Related

Gwtp Autobean and rest

I have InfraNameModel (Rest-type) to work with JSON
public interface IInfraNameBeanFactory extends AutoBeanFactory {
IInfraNameBeanFactory INSTANCE = GWT.create(IInfraNameBeanFactory.class);
AutoBean<InfraNameModel> infraName();
AutoBean<InfraNameListModel> results();
}
public interface InfraNameListModel {
List<InfraNameModel> getResults();
void setResults(List<InfraNameModel> results);
}
public class InfraNameListModelImpl implements InfraNameListModel {
private List<InfraNameModel> results;
#Override
public List<InfraNameModel> getResults() {
return results;
}
#Override
public void setResults(List<InfraNameModel> results) {
this.results = results;
}
}
public interface InfraNameModel {
String getInfraName();
void setInfraName(String infraName);
}
public class InfraNameModelImpl implements InfraNameModel {
private String infraName;
#Override
public String getInfraName() {
return infraName;
}
#Override
public void setInfraName(String infraName) {
this.infraName = infraName;
}
}
I wanted to make them into a separate JAR
To make it common for the client and the server
But now I have errors
[WARN] Class by.models.infraNameModel.InfraNameModel is used in Gin, but not available in GWT client code.
Is it real to pull such beans into a separate library?

How to Create Lookup by Account Type using DimensionDynamicAccountController?

I have a problem.
I have in my new table two new fields
1) Name -> AccountNum, EDT--> DimensionDynamicAccount
2) Name -> AccountType, EDT--> LedgerJournalACType
class declaration
:
public class FormRun extends ObjectRun
{
DimensionDynamicAccountController dimAccountController;
}
init (for the form):
public void init()
{
super();
dimAccountController = DimensionDynamicAccountController::construct(
MyTable_ds,
fieldstr(MyTable, LedgerDimension),
fieldstr(MyTable, AccountType));
}
4. Override the following methods on the Segmented Entry control instance in the form design.
public void jumpRef()
{
dimAccountController.jumpRef();
}
public void loadAutoCompleteData(LoadAutoCompleteDataEventArgs _e)
{
super(_e);
dimAccountController.loadAutoCompleteData(_e);
}
public void segmentValueChanged(SegmentValueChangedEventArgs _e)
{
super(_e);
dimAccountController.segmentValueChanged(_e);
}
public void loadSegments()
{
super();
dimAccountController.parmControl(this);
dimAccountController.loadSegments();
}
public boolean validate()
{
boolean isValid;
isValid = super();
isValid = dimAccountController.validate() && isValid;
return isValid;
}
5. Override the following methods on the data source field that backs the Segmented Entry control.
public Common resolveReference(FormReferenceControl _formReferenceControl)
{
return dimAccountController.resolveReference();
}
Now my problem is Lookup only works for AccountType=="Ledger" not for customer, Vendor etc...
If I have a AccountType == Vendor or similant but different to Ledger I see this
I would want to have same the same thing that's in the LedgerJournalTrans Form
There is a solution,
thanks all,
enjoy
This might be too obvious, but I think you're missing the lookup() method.
See:
\Forms\LedgerJournalTransDaily\Designs\Design\[Tab:Tab]\[TabPage:OverViewTab]\[Grid:overviewGrid]\SegmentedEntry:LedgerJournalTrans_AccountNum\Methods\lookup
public void lookup()
{
if (!ledgerJournalEngine.accountNumLookup(ledgerJournalTrans_AccountNum,
ledgerJournalTrans,
ledgerJournalTrans.OffsetAccountType,
ledgerJournalTrans.parmOffsetAccount(),
ledgerJournalTrans_Asset))
{
super();
}
}

Unreachable security context using Feign RequestInterceptor

The goal is to attach some data from security context using RequestInterceptor, but the problem, that the calling SecurityContextHolder.getContext().getAuthentication() always returns null even though it is not null (I am sure 100%).
As I understand that's because the Interceptor is created and is being run in other thread.
How could I solve this problem and get actual data from security context?
My service:
#FeignClient(value = "api", configuration = { FeignConfig.class })
public interface DocumentService {
#RequestMapping(value = "/list", method = RequestMethod.GET)
DocumentListOperation list();
}
My FeignConfig class:
#Bean
public RequestInterceptor requestInterceptor() {
return new HeaderInterceptor(userService);
}
public class HeaderInterceptor implements RequestInterceptor {
private UserService userService;
public HeaderInterceptor(UserService userService) {
this.userService = userService;
}
#Override
public void apply(RequestTemplate requestTemplate) {
Authentication a = SecurityContextHolder.getContext().getAuthentication()
requestTemplate.header("authentication", a.toString());
}
}
I managed to figure it out, thanks to the article I found here
Firstly you need to initiliaze HystrixRequestContext HystrixRequestContext.initializeContext();.
You have to create your own Context in which you will store information you need to pass to Hystrix child threads.
Here is example:
public class UserHystrixRequestContext {
private static final HystrixRequestVariableDefault<User> userContextVariable = new HystrixRequestVariableDefault<>();
private UserHystrixRequestContext() {}
public static HystrixRequestVariableDefault<User> getInstance() {
return userContextVariable;
}
}
You have to register new concurrency strategy that would wrap Callable interface
#Component
public class CustomHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
public CustomHystrixConcurrencyStrategy() {
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
}
#Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
return new HystrixContextWrapper<T>(callable);
}
public static class HystrixContextWrapper<V> implements Callable<V> {
private HystrixRequestContext hystrixRequestContext;
private Callable<V> delegate;
public HystrixContextWrapper(Callable<V> delegate) {
this.hystrixRequestContext = HystrixRequestContext.getContextForCurrentThread();
this.delegate = delegate;
}
#Override
public V call() throws Exception {
HystrixRequestContext existingState = HystrixRequestContext.getContextForCurrentThread();
try {
HystrixRequestContext.setContextOnCurrentThread(this.hystrixRequestContext);
return this.delegate.call();
} finally {
HystrixRequestContext.setContextOnCurrentThread(existingState);
}
}
}
}
So before calling Callable object we set new thread's Context to parent's context.
After that is done you should be able to access your new defined context inside Hystrix child threads
User = UserHystrixRequestContext.getInstance().get();
Hope that will help someone.

Injecting a Factory that accepts a Parameter with AutoFac

I've read over several examples that were more complex then I needed and I'm having trouble distilling this down to a simple, concise pattern.
Let's say I have an interface names ICustomService and multiple implementations of ICustomService. I also have a class Consumer that needs to determine at run time which ICustomService to use based upon a parameter.
So I create a classes as follows:
public class Consumer
{
private CustomServiceFactory customServiceFactory;
public Consumer(CustomServiceFactory _customServiceFactory)
{
customServiceFactory = _customServiceFactory;
}
public void Execute(string parameter)
{
ICustomService Service = customServiceFactory.GetService(parameter);
Service.DoSomething();
}
}
public class CustomServiceFactory
{
private IComponentContext context;
public CustomServiceFactory(IComponentContext _context)
{
context = _context;
}
public ICustomService GetService(string p)
{
return context.Resolve<ICustomService>(p); // not correct
}
}
public class ServiceA : ICustomService
{
public void DoSomething()
{
}
}
public class ServiceB : ICustomService
{
public void DoSomething()
{
}
}
Is there an advantage to having my factory implement an interface? How do I fix my factory and register these classes with Autofac so that Consumer.Execute("A") calls DoSomething on WorkerA and Consumer.Execute("B") calls DoSomething on WorkerB?
Thank you
You would register your implementations of ICustomService with keys. For example:
builder.RegisterType<FooService>.Keyed<ICustomService>("someKey");
builder.RegisterType<BarService>.Keyed<ICustomService>("anotherKey");
and then your factory method would be:
public ICustomService GetService(string p)
{
return context.ResolveKeyed<ICustomService>(p);
}
But, you can take this a step further and decouple CustomServiceFactory from IComponentContext:
public class CustomServiceFactory
{
private Func<string, ICustomService> _create;
public CustomServiceFactory(Func<string, ICustomService> create)
{
_create = create;
}
public ICustomService GetService(string p)
{
return _create(p);
}
}
which you would register like so:
builder.Register(c => {
var ctx = c.Resolve<IComponentContext>();
return new CustomServiceFactory(key => ctx.ResolveKeyed<ICustomService>(key));
});
And at that point, assuming CustomServiceFactory doesn't have any other behavior that was omitted for the question, then you as might as well just use and register Func<string, ICustomService> directly.

CDI - Injecting objects dynamically at runtime

How do I inject objects at runtime? For example, if I want to inject DerviedOne, DerivedTwo objects at runtime into the Test class in the following example, how do I do that? I found a few examples in Spring, but I'm not using Spring. This is a Dynamic Web Project with CDI using Java EE 6.
public abstract class Base
{
public Base(String initiator)
{
this.initiator = initiator;
}
public abstract void process();
public void baseProcess()
{
System.out.println("base process");
process();
}
public String getInitiator()
{
return initiator;
}
private String initiator;
}
public class BaseUtil
{
public long start()
{
return System.currentTimeMillis();
}
public long stop()
{
return System.currentTimeMillis();
}
}
public class DerivedOne extends Base
{
public DerivedOne(String initiator)
{
super(initiator);
}
#Override
public void process()
{
long start = baseUtil.start();
System.out.println(getInitiator() + " process");
long stop = baseUtil.stop();
System.out.println(stop - start);
}
#javax.inject.Inject
private BaseUtil baseUtil;
}
public class DerivedTwo extends Base
{
public DerivedTwo(String initiator)
{
super(initiator);
}
#Override
public void process()
{
long start = baseUtil.start();
System.out.println(getInitiator() + " process");
long stop = baseUtil.stop();
System.out.println(stop - start);
}
#javax.inject.Inject
private BaseUtil baseUtil;
}
#Startup
#Singleton
public class Test
{
#PostConstruct
public void init()
{
String initiator = "two";
Base base = null;
if("one".equals(initiator))
{
base = new DerivedOne("DerivedOne");
}
else if("two".equals(initiator))
{
base = new DerivedTwo("DerivedTwo");
}
base.baseProcess();
}
}
If you want to select one implementation based on runtime conditions You can use a producer method with qualifiers.
For testing CDI application I highly recommend Arquillian.
http://arquillian.org/