I have Weld SE, bootstraped this way:
WeldContainer weld = new Weld().initialize();
And the following bean
#ApplicationScoped
public class EntityManagerStoreImpl implements EntityManagerStore {
static { System.out.println(" AAAAAA EMSI static"); }
public EntityManagerStoreImpl() {
System.out.println(" AAAAAA EMSI constructor");
}
public void init( #Observes ContainerInitialized containerInitialized ) {
System.out.println(" AAAAAA EMSI init");
}
...
}
According to Weld docs, the init() method should be called.
But it's not. Other beans are working fine.
What can be wrong?
Oh... I should have read the docs more carefuly.
ContainerInitialized is currently only fired from StartMain helper class.
I don't like that, I'd expect it to be fired from Weld.initialize().
So I created https://issues.jboss.org/browse/WELD-949
(Pls vote if you share this oppinion with me.)
Related
I'm trying to code a RSS-feed reader with a configured set of RSS-feeds. I thought that a good approach is to solve that by coding a prototype-#Bean and call it with each RSS-feed found in the configuration.
However, I guess that I'm missing a point here as the application launches, but nothing happens. I mean the beans are created as I'd expect, but there is no logging happening in that handle()-method:
#Component
public class HomeServerRunner implements ApplicationRunner {
private static final Logger logger = LoggerFactory.getLogger(HomeServerRunner.class);
#Autowired
private Configuration configuration;
#Autowired
private FeedConfigurator feedConfigurator;
#Override
public void run(ApplicationArguments args) throws Exception {
List<IntegrationFlow> feedFlows = configuration.getRssFeeds()
.entrySet()
.stream()
.peek(entry -> System.out.println(entry.getKey()))
.map(entry -> feedConfigurator.feedFlow(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
// this one appears in the log-file and looks good
logger.info("Flows: " + feedFlows);
}
}
#Configuration
public class FeedConfigurator {
private static final Logger logger = LoggerFactory.getLogger(FeedConfigurator.class);
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public IntegrationFlow feedFlow(String name, FeedConfiguration configuration) {
return IntegrationFlows
.from(Feed
.inboundAdapter(configuration.getSource(), getElementName(name, "adapter"))
.feedFetcher(new HttpClientFeedFetcher()),
spec -> spec.poller(Pollers.fixedRate(configuration.getInterval())))
.channel(MessageChannels.direct(getElementName(name, "in")))
.enrichHeaders(spec -> spec.header("feedSource", configuration))
.channel(getElementName(name, "handle"))
//
// it would be nice if the following would show something:
//
.handle(m -> logger.debug("Payload: " + m.getPayload()))
.get();
}
private String getElementName(String name, String postfix) {
name = "feedChannel" + StringUtils.capitalize(name);
if (!StringUtils.isEmpty(postfix)) {
name += "." + postfix;
}
return name;
}
}
What's missing here? It seems as if I need to "start" the flows somehow.
Prototype beans need to be "used" somewhere - if you don't have a reference to it anywhere, no instance will be created.
Further, you can't put an IntegrationFlow #Bean in that scope - it generates a bunch of beans internally which won't be in that scope.
See the answer to this question and its follow-up for one technique you can use to create multiple adapters with different properties.
Alternatively, the upcoming 1.2 version of the DSL has a mechanism to register flows dynamically.
In our project we have following modules scout.client, scout.server, scout.shared and backend.
backend has no dependencies to scout.server and scout.shared, but scout.server has dependencies to backend.
Inside the backend project we have all business logic and calling all outside services.
We use the Scout Bean Manager to manage the instances of the Backend-Services in our scout.server:
BEANS.getBeanManager().registerClass(CarService.class);
BEANS.getBeanManager().registerClass(PartnerService.class);
Both, CarService.class and PartnerService.class are in the backend.
Is this registration correct? Or should I register the classes using the registerBean(..) method instead of registerClass(..)?
Question derived from an other question asked by #marko-zadravec
As explained in the registerClass(..) JavaDoc, if you do:
public class RegisterBeansListener implements IPlatformListener {
#Override
public void stateChanged(PlatformEvent event) {
if (event.getState() == IPlatform.State.BeanManagerPrepared) {
// register the class directly:
BEANS.getBeanManager().registerClass(BeanSingletonClass.class);
}
}
}
This is the same as:
public class RegisterBeansListener implements IPlatformListener {
#Override
public void stateChanged(PlatformEvent event) {
if (event.getState() == IPlatform.State.BeanManagerPrepared) {
// register with meta information
BeanMetaData beanData = new BeanMetaData(PartnerService.class);
BEANS.getBeanManager().registerBean(beanData);
}
}
}
Meaning that you will get a new instance of the PartnerService each time you call BEANS.get(IPartnerService.class). (see Bean Scopes in the Scout Docs).
If you want your bean to have only one instance for your entire application you should register it like that:
public class RegisterBeansListener implements IPlatformListener {
#Override
public void stateChanged(PlatformEvent event) {
if (event.getState() == IPlatform.State.BeanManagerPrepared) {
// register with meta information
BeanMetaData beanData = new BeanMetaData(PartnerService.class)
.withApplicationScoped(true);
BEANS.getBeanManager().registerBean(beanData);
}
}
}
I recommend setting a specific Order like in this answer only for test purpose.
I am actually working in an ASP.Net MVC 4 web application where we are using NInject for dependency injection. We are also using UnitOfWork and Repositories based on Entity framework.
We would like to use Quartz.net in our application to start some custom job periodically. I would like that NInject bind automatically the services that we need in our job.
It could be something like this:
public class DispatchingJob : IJob
{
private readonly IDispatchingManagementService _dispatchingManagementService;
public DispatchingJob(IDispatchingManagementService dispatchingManagementService )
{
_dispatchingManagementService = dispatchingManagementService ;
}
public void Execute(IJobExecutionContext context)
{
LogManager.Instance.Info(string.Format("Dispatching job started at: {0}", DateTime.Now));
_dispatchingManagementService.DispatchAtomicChecks();
LogManager.Instance.Info(string.Format("Dispatching job ended at: {0}", DateTime.Now));
}
}
So far, in our NInjectWebCommon binding is configured like this (using request scope):
kernel.Bind<IDispatchingManagementService>().To<DispatchingManagementService>();
Is it possible to inject the correct implementation into our custom job using NInject ? and how to do it ? I have read already few posts on stack overflow, however i need some advises and some example using NInject.
Use a JobFactory in your Quartz schedule, and resolve your job instance there.
So, in your NInject config set up the job (I'm guessing at the correct NInject syntax here)
// Assuming you only have one IJob
kernel.Bind<IJob>().To<DispatchingJob>();
Then, create a JobFactory: [edit: this is a modified version of #BatteryBackupUnit's answer here]
public class NInjectJobFactory : IJobFactory
{
private readonly IResolutionRoot resolutionRoot;
public NinjectJobFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
// If you have multiple jobs, specify the name as
// bundle.JobDetail.JobType.Name, or pass the type, whatever
// NInject wants..
return (IJob)this.resolutionRoot.Get<IJob>();
}
public void ReturnJob(IJob job)
{
this.resolutionRoot.Release(job);
}
}
Then, when you create the scheduler, assign the JobFactory to it:
private IScheduler GetSchedule(IResolutionRoot root)
{
var schedule = new StdSchedulerFactory().GetScheduler();
schedule.JobFactory = new NInjectJobFactory(root);
return schedule;
}
Quartz will then use the JobFactory to create the job, and NInject will resolve the dependencies for you.
Regarding scoping of the IUnitOfWork, as per a comment of the answer i linked, you can do
// default for web requests
Bind<IUnitOfWork>().To<UnitOfWork>()
.InRequestScope();
// fall back to `InCallScope()` when there's no web request.
Bind<IUnitOfWork>().To<UnitOfWork>()
.When(x => HttpContext.Current == null)
.InCallScope();
There's only one caveat that you should be aware of:
With incorrect usage of async in a web request, you may mistakenly be resolving a IUnitOfWork in a worker thread where HttpContext.Current is null. Now without the fallback binding, this would fail with an exception which would show you that you've done something wrong. With the fallback binding however, the issue may present itself in an obscured way. That is, it may work sometimes, but sometimes not. This is because there will be two (or even more) IUnitOfWork instances for the same request.
To remedy this, we can make the binding more specific. For this, we need some parameter to tell us to use another than InRequestScope(). Have a look at:
public class NonRequestScopedParameter : Ninject.Parameters.IParameter
{
public bool Equals(IParameter other)
{
if (other == null)
{
return false;
}
return other is NonRequestScopedParameter;
}
public object GetValue(IContext context, ITarget target)
{
throw new NotSupportedException("this parameter does not provide a value");
}
public string Name
{
get { return typeof(NonRequestScopedParameter).Name; }
}
// this is very important
public bool ShouldInherit
{
get { return true; }
}
}
now adapt the job factory as follows:
public class NInjectJobFactory : IJobFactory
{
private readonly IResolutionRoot resolutionRoot;
public NinjectJobFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return (IJob) this.resolutionRoot.Get(
bundle.JobDetail.JobType,
new NonrequestScopedParameter()); // parameter goes here
}
public void ReturnJob(IJob job)
{
this.resolutionRoot.Release(job);
}
}
and adapt the IUnitOfWork bindings:
Bind<IUnitOfWork>().To<UnitOfWork>()
.InRequestScope();
Bind<IUnitOfWork>().To<UnitOfWork>()
.When(x => x.Parameters.OfType<NonRequestScopedParameter>().Any())
.InCallScope();
This way, if you use async wrong, there'll still be an exception, but IUnitOfWork scoping will still work for quartz tasks.
For any users that could be interested, here is the solution that finally worked for me.
I have made it working doing some adjustment to match my project. Please note that in the method NewJob, I have replaced the call to Kernel.Get by _resolutionRoot.Get.
As you can find here:
public class JobFactory : IJobFactory
{
private readonly IResolutionRoot _resolutionRoot;
public JobFactory(IResolutionRoot resolutionRoot)
{
this._resolutionRoot = resolutionRoot;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try
{
return (IJob)_resolutionRoot.Get(
bundle.JobDetail.JobType, new NonRequestScopedParameter()); // parameter goes here
}
catch (Exception ex)
{
LogManager.Instance.Info(string.Format("Exception raised in JobFactory"));
}
}
public void ReturnJob(IJob job)
{
}
}
And here is the call schedule my job:
public static void RegisterScheduler(IKernel kernel)
{
try
{
var scheduler = new StdSchedulerFactory().GetScheduler();
scheduler.JobFactory = new JobFactory(kernel);
....
}
}
Thank you very much for your help
Thanks so much for your response. I have implemented something like that and the binding is working :):
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var resolver = DependencyResolver.Current;
var myJob = (IJob)resolver.GetService(typeof(IJob));
return myJob;
}
As I told before I am using in my project a service and unit of work (based on EF) that are both injected with NInject.
public class DispatchingManagementService : IDispatchingManagementService
{
private readonly IUnitOfWork _unitOfWork;
public DispatchingManagementService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
}
Please find here how I am binding the implementations:
kernel.Bind<IUnitOfWork>().To<EfUnitOfWork>()
kernel.Bind<IDispatchingManagementService>().To<DispatchingManagementService>();
kernel.Bind<IJob>().To<DispatchingJob>();
To resume, the binding of IUnitOfWork is done for:
- Eevery time a new request is coming to my application ASP.Net MVC: Request scope
- Every time I am running the job: InCallScope
What are the best practices according to the behavior of EF ? I have find information to use CallInScope. Is it possible to tell NInject to get a scope ByRequest everytime a new request is coming to the application, and a InCallScope everytime my job is running ? How to do that ?
Thank you very much for your help
I basically am trying to inject a #Stateless bean with a local interface into a class annotated with #Named! My understanding is that injection is only possible when the injection point is managed (makes perfect sense), so for example it wouldn't be possible to inject into a POJO but you could inject into a Servlet, a JSF managed or another EJB.
I would have thought that it would have been possible to subsequently use it with #Named! However I get a NullPointerException that specifically seems to imply that this in fact doesn't seem possible!?
My classes look like this (stripped for clarity);
#Named
public class EmailUtil {
// Logger-------------------------------------------------------------------
private static final Logger LOG = Logger.getLogger(EmailUtil.class.getName());
// Constructor--------------------------------------------------------------
public EmailUtil() {
}
// EJB----------------------------------------------------------------------
#EJB AuditDAO audit;
// Methods------------------------------------------------------------------
public void sendEmail(
String emailSender,
String emailRecipient,
String emailSubject,
String emailHtmlBody,
String emailTextBody) throws FailedEmailException {
... code removed for clarity ...
// Call Amazon SES to send the message
try {
new SES().getClient().sendEmail(request);
// Create an audit log of the event
audit.create("Email sent to " + emailSender);
} catch (AmazonClientException ace) {
LOG.log(Level.SEVERE, ace.getMessage(), ace);
throw new FailedEmailException();
} catch (Exception e) {
LOG.log(Level.SEVERE, e.getMessage(), e);
}
}
}
#Stateless
public class AuditDAOImpl implements AuditDAO {
// Logger-------------------------------------------------------------------
private static final Logger LOG = Logger.getLogger(AuditDAOImpl.class.getName());
// EntityManager------------------------------------------------------------
#PersistenceContext(unitName = "iConsultPU")
private EntityManager em;
#Override
public void create(String event) {
String subject;
try {
/*
* If the current subject has authenticated and created a session we
* want to register their ID. However it is possible that a subject
* does not have an ID so we want to set it to unknown.
*/
subject = SecurityUtils
.getSubject()
.getPrincipals()
.asList()
.get(1)
.toString();
} catch (Exception e) {
subject = "UNKNOWN";
}
Audit audit = new Audit();
audit.setUserId(subject);
audit.setEventTime(Calendar.getInstance());
audit.setEvent(event);
em.persist(audit);
}
}
#Local
public interface AuditDAO {
public void create(String event);
}
I've tried using #Inject as well but that doesn't seem to work either. Have I misunderstood the specification or just poorly implemented it?
You should be injecting your dependencies. So if your EmailUtil is being manually constructed, injection won't work. It needs to be container managed. So if you use a servlet, or any managed bean, you can #Inject it. CDI injection only works for managed objects.
You can do some additional work arounds, such as manually invoking it against a constructed instance. Take a look at this question for an example like that: Parallel webservices access in a Weld CDI environment
Do you have the beans.xml in the correct location? Injection for #Named (and other CDI beans) is handled by CDI, which isn't started unless you have the beans.xml file in the correct location (WEB-INF for war and META-INF for jar).
Trying to get Unit Tests to work when using Spring RestTemplate and I18N. Everything in the setup works fine for all the other test cases.
Based upon what I read, this is what I put into the Java Config:
#Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
return new LocaleChangeInterceptor();
}
#Bean
public DefaultAnnotationHandlerMapping handlerMapping() {
DefaultAnnotationHandlerMapping mapping = new DefaultAnnotationHandlerMapping();
Object[] interceptors = new Object[1];
interceptors[0] = new LocaleChangeInterceptor();
mapping.setInterceptors(interceptors);
return mapping;
}
#Bean
public AnnotationMethodHandlerAdapter handlerAdapter() {
return new AnnotationMethodHandlerAdapter();
}
Then in my usage with RestTemplate I have:
public MyEntity createMyEntity(MyEntity bean) {
Locale locale = LocaleContextHolder.getLocale();
String localeString = "";
if (locale != Locale.getDefault()) {
localeString = "?locale=" + locale.getLanguage();
}
HttpEntity<MyEntity> req = new HttpEntity<MyEntity>(bean);
ResponseEntity<MyEntity> response = restTemplate.exchange(restEndpoint + "/url_path" + localeString, HttpMethod.POST, req, MyEntity.class);
return response.getBody();
}
While this could be cleaned up a bit, it should work - but the LocalChangeInterceptor never gets invoked. I am debugging this now and will post again as soon as I figure it out - but in the hope this is a race condition that I lose - does anyone know why?
Was lucky and stumbled upon this thread. One of the notes clued me into the right direction. You don't need all those beans in the Java Config. But if you are using #EnableWebMvc as I am, but I didn't know it was important enough to even mention, all you need to do in your Java Config is:
#Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
return new LocaleChangeInterceptor();
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LocaleChangeInterceptor());
super.addInterceptors(registry);
}
Add the one bean for the Interceptor and then override the method to add the interceptor. Here my configuration class (annotated with #Configuration and #EnableWebMvc) also extends WebMvcConfigurerAdapter, which should be common usage.
This, at least, worked for me. Hope it may help someone else.