Liferay: perform an action when a -LocalServiceUtil is available - liferay

I have implemented a functional Liferay service using service builder and I want to call a method on the -LocalServiceUtil class just as soon as I possibly can. This is a task I wish to perform when the service starts and also when the service is redeployed.
Even though all the methods on the -LocalServiceUtil class are static, they will throw a BeanLocatorException if they are called too soon.
com.liferay.portal.kernel.bean.BeanLocatorException: BeanLocator has not been set for servlet context portal-navigation-impl
Is there any way to call a method on the -LocalServiceImpl instance or otherwise so that I can do this?
Thank you

As you speak about the initialization order: I'm not 100% sure about this, but I'd write a startup action. This gets run everytime a hook (or plugin) starts up - including a redeploy. Sounds like what you want - and if the initialization order works, this is your solution.
Otherwise: Create a separate hook that's dependent on the one that you're currently using. That will be restarted as well, but only run once the hook providing the *-LocalService did already start up. (dependency is declared in liferay-plugin-package.properties, with the key required-deployment-context - this is from memory - somebody correct me if I'm wrong.)

Related

Guidewire PolicyCenter The object you are trying to update was changed by another user. Please try your change again

I'm having this weard mistake "The object you are trying to update was changed by another user. Please try your change again." I would like to know what is the reason of this without context. There are no logs about it, no exception stacktrace, no information about this mistake in documentation. I believe this is something about Bundles but I want to now the exact reason
GW throws several exceptions related, by example ConcurrentDataChangeException, DBVersionConflictException depending of entity type. It occurs when a bean is modified concurrent by two or more transactions (bundle).
This error usually happens because on one bundle two transaction changes are trying to commit where prior bundle is still not committed.
Let us understand with one example- There is user which does a policy change to add any contact or any other business operation. And at the same time another user open same transaction in his GW PC UI and tries to do some business operation at this GW system throws this error on UI because the pervious bundle is still not committed.
The error trace leads you to some OOTB java classed and I think you can get it from PCLogs from PC UI Server logs.
Hopes this clarifies you.
Actually this happens because your object was updated by someone else on the DB during your db read from the DB and your attempt to write it back into the DB.
GW does this by leveraging the version check from your database object.
The exception message actually tells you who and when did the conflicting update. There're no stack traces that will point you to the cause of the other update.
Root causes might be several - from distributed cache in clustered env going out of sync to actually having some other party doing work on the same entities as you do. So the fix is per case really.

Overriding configure does not work for the initial configuration

I need to override configure() on my waveform and I tried to do it as suggested in the manual, by overriding PropertySet_impl::configure in my .[h,cpp] but calling the PropertySet_impl::configure in my override. It works when I configure my component using a python script, but it does NOT appear to be called for the initial configure by DomainManager using .prf.xml in the domain profile.
Do you send in this initial configure some other way and is there a way I can override for these too?
Try using the setPropertyConfigureImpl for properties that need custom configure logic instead of overriding configure. I believe this is invoked on the initial call to set properties.
Starting with REDHAWK 2.0, components support a new method initializeProperties() that is called once when the component is created, prior to the call to initialize(). Any properties of kind "property" are given their initial values via this call, using overridden values if provided. Legacy "configure" kind properties are still initialized via a configure() call following initialize().
If setting configure functions for your properties is sufficient, I'd encourage that approach. If you expect them to be called at initialization time, you'll want to set them in the C++ constructor, though, not the REDHAWK constructor() method.
Based on your question, property listeners are probably not suitable; property change notification is not triggered by initializeProperties(), only configure(). Note that the C++ interface is addPropertyListener(); registerPropertyListener() is a CORBA method that supports external notification of property changes.

Intercepting injection

I am injecting repositories into a class, and once I've injected the repositories, I'm assigning my context to each of the repositories so I have my unit of work.
What I'm trying to figure out is, is there a way for me to automatically assign my Unit of Work to each repository as I inject it so that a developer doesn't have to consider this when setting up their code. I've already got my unit of work configured in my base class, the one the developer will be inheriting from.
Can I do something like;
Bind<I>().To<S>().WhenInjectedInto<IBaseClass>( i,b => { i.UnitOfWork = b.UnitOfWork });
But not have to repeat that pattern every time?
[UPDATE]
I'm looking at ways to figure out if Ninject is injecting and what from into,
https://github.com/ninject/ninject.extensions.interception
I'm trying to look through the tests to see if this is far off base. Any recommendations?
I think the better way would be to inject the context into the repositoies using constructor injection. In a web project you can use InRequestScope for the context binding. For a WPF/WinForms/Console application have a look at Ninject.Extensions.NamedScope. You can define that a single context is used for all dependencies of you IBaseClass.

Multithreading using Wcf

HI i am new to the the whole programming thing, i have been given a task to multithread 4 stored procedures where each thread runs asynchronously so that the user can get output real quick i have to do it using WCF can anyone help me out with this. Initially what i am trying to do is taking each procedure and getting how much time it takes to execute using parametrizedthreadstart, but i am not sure how to go about it.
Considering you are new to the whole programming thing, you can follow these very basic steps to get thing done.
Create a new WCF service.
Add 4 methods each calling one stored procedure.
Add parameters to the methods which are required by stored procedures.
For Example if your stored procedure is - MySP(varchar name) then your WCF method will
be - MySP(string name);
Now depoly your service in IIS or windows service or Console App or wherever you want.
Create a client application, again it could be anything ConsoleApp or Win Form etc.
Add a reference to your service.
Instantiate service class and call there Async version. By Async I mean there you'll
see all of the four methods with Async attached.
For Example you will find your MySP(string name) method as MySPAsync(string name)
Also there will be MySPCompleted event, subscribe to it.
Now all of your methods are running asynchronously whenever they finish execution they'll call your subscribed methods.
I hope this helps you get started :)
There are a couple of different ways to do this. At the highest level, you can place each service request in it's own service endpoint. This could be defining endpoints for each method, or if you are hosting in IIS, placing each service it's own website. At the lower level, you could define callbacks for each method so that WCF will not block while the method calls are taking place.

Lucene.Net and I/O Threading issue

I have an indexing function named "Execute()" using IndexWriter to index my site's content. It works great if I simply called it from a web page, but failed when I have it as a delegate parameter into System.Threading.Thread. Strangely though, it always work on my local dev machine, it only fails when I uploads to a shared host.
This is the error message I got
"Lock obtain timed out: SimpleFSLock error...."
Below is the failed code (but only fails on a shared host)
Scheduler scheduler = new Scheduler();
System.Threading.Thread schedulerThread = new System.Threading.Thread(scheduler.Execute);
Below is the code that works (work both on my local machine and on shared host)
Scheduler scheduler = new Scheduler();
schedulre.Execute();
Now, some ppl said, it could be a bad left over from the previous debugging session, so before I instantiated the IndexWriter, I did
if (IndexReader.IsLocked(indexingFolder))
{
log.Debug("it is locked");
IndexReader.Unlock(FSDirectory.GetDirectory(indexingFolder));
}
else
{
log.Debug("it is not locked");
}
and guess what? my log says, it is not locked.
So now I'm pretty sure it's caused by the System.Thread.Threading, but I just have no clue as to how to fix it.
Thanks
Check that on the shared host, the thread has the same permissions to the index folder as you do on the development machine/shared host.
Update: You can find what Principal the thread is running under by interrogating the thread's CurrentPrincipal property. Though this is a read-write property, you may not have the permissions to set this property in your shared-host environment.
You might find this post helpful.
Thanks everyone and especially to Vinay for pointing me in the right direction. After much tracing, i finally decided to take a look at the source and see what's there.
In "IndexWriter", you have
Lock #lock = this.directory.MakeLock("write.lock");
if (!#lock.Obtain(this.writeLockTimeout))
which is pointed to the SimpleFSLock implementation. The culprit was
new FileStream(this.lockFile.FullName, FileMode.CreateNew).Close();
by creating a new thread, internally, it throws a system.unauthorizedaccessexception, according to msdn here
When starting a new thread, System.Security.Principal.WindowsIdentity.GetCurrent() returns the identity of the process, not necessarily the identity of the code that called Thread.Start(). This is important to remember when starting asynchronous delegates or threads in an impersonated ASP.NET thread.
If you are in ASP.NET and want the new thread to start with the impersonated WindowsIdentity, pass the WindowsIdentity to the ThreadStart method. Once in the ThreadStart method, call WindowsIdentity.Impersonate().
Such, I solved my issue by impersonate the IIS account running my application in "Execute()" function and all problems are resolved.
Thanks again to all.
Probably the worst one to try and answer this since I haven't used lucene / shared hosting, but SimpleFSLock sounds like it's locking the lucene index file by using an explicit lock file on the file system (not quite the same as locking in threading). I'd say check to make sure you have configured the proper file paths and that file permissions are set correctly.
Otherwise, hopefully someone more familiar with Lucene.net can answer.
I believe the problem is with a write lock file in the Lucene index directory.
Go and list the directory's files.
In Java Lucene, you would have seen a file named write.lock in the index directory,
meaning that the index was not properly closed last time (maybe a process was abruptly stopped). In Lucene.net, look for a similarly named empty file.
I believe the same mechanism will be used in Lucene.net.
Try finding that file, erasing it and restarting Lucene.net.

Resources