Accessing Magnolia TemplatingFunctions from inside a controller - java

Is it possible to serve different experiences depending on whether the user is in edit mode? I've noticed that the following method exists; however it is not static:
info.magnolia.templating.functions.TemplatingFunctions.isEditMode()
Is there a way to access the isEditMode() method from inside a controller? Is an instance of it defined somewhere which can be accessed? I imagine that creating a new instance of the TemplatingFunctions class won't help ...
I've looked at using #Inject; however I keep getting issues on injection of all parameters.
#Inject
public ModelAndView renderView(Model model, Node node, TemplatingFunctions templatingFunctions) throws RepositoryException {
if (templatingFunctions.isEditMode()) {
}
}

When I checked what that method does, I found out that its a combination of two functions.
Components.getComponent(ServerConfiguration.class).isAdmin()
and
aggregationStateProvider.get().isPreviewMode()
It seems that you should be injecting a provider to know if user is in preview mode
Provider<AggregationState> aggregationStateProvider
As a general remark, one may understand if a component is injectable or not from the related modules configuration which is under myModule/src/main/resources/META-INF/mymodule.xml. If a component is listed there, then is it injectable in other classes. For instance you should have no problems injecting a type of TemplatinFunctions because it is indeed defined as;
<component>
<type>info.magnolia.templating.functions.TemplatingFunctions</type>
<implementation>info.magnolia.templating.functions.TemplatingFunctions</implementation>
<scope>singleton</scope>
</component>
Further reading can be found at https://documentation.magnolia-cms.com/display/DOCS/Dependency+injection+and+inversion+of+control
Hope this helps,

Related

When and how cglib-proxied component instance is created

I'd like to learn if there are some rules / conditions that a Spring component is wrapped (proxied) by CGLIB. For example, take this case:
#Component
public class TestComponent {
}
#Service
//#Transactional(rollbackFor = Throwable.class)
public class ProcessComponent {
#Autowired
private TestComponent testComponent;
public void doSomething(int key) {
// try to debug "testComponent" instance here ...
}
}
If we let it like this and debug the testComponent field inside the method, then we'll see that it's not wrapped by CGLIB.
Now if we uncomment the #Transactional annotation and debug, we'll find that the instance is wrapped: it's of type ProcessComponent$$EnhancerByCGLIB$$14456 or something like that. It's clearly because Spring needs to create a proxy class to handle the transaction support.
But I'm wondering, is there any way that we can detect how and when does this wrapping happen ? For example, some specific locations in Spring's source code to debug into to find more information; or some documentations on the rules of how they decide to create a proxy.
For your information, I need to know about this because I'm facing a situation where some component (not #Transactional, above example is just for demonstrating purpose) in my application suddenly becomes proxied (I found a revision a bit in the past where it is not). The most important issue is that this'll affect such components that also contain public final methods and another issue (also of importance) is that there must have been some unexpected changes in the design / structure of classes. For these kind of issues, of course we must try to find out what happened / who did the change that led to this etc...
One note is that we have just upgraded our application from Spring Boot 2.1.0RELEASE to 2.1.10RELEASE. And checking the code revision by revision up till now is not feasible, because there have been quite a lot of commits.
Any kind of help would be appreciated, thanks in advance.
You could debug into org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(Class, String, TargetSource).
If any advisor is found, the bean will be proxied.
If you use a #Lookup method injection it will also proxy the component class.

How to mock a method of bean inside spring util:list (ref)

here the situation:
i got some beans (called Systems). These beans work with external system to gather data and do more (like analyze them, or store them in database etc.). These systems also got some beans to do the work (the work called before, gather / read, analyze, store, etc).
I got a spring context xml where these beans (systems) are defined like:
<bean id="SomeSystem" class"..."/>
All these systems have the same Interface...let's call it "MommyInterfaceSystem"...
And i got also a simple util:list config, like this:
<util:list id="MyAwesomeSystemsList">
<ref bean="SomeSystem"/>
<ref bean="AnotherSystem"/>
...
</util:list>
As you can see i got some "Systems" like "SomeSystem" and "AnotherSystem" - both implementing "MommyInterfaceSystem"...whatever...
These systems are get called over another Class. Let's call it "GatherInformationFromSystems".
This class has this structure:
public class GatherInformationFormSystems {
#Resource(name "MyAwesomeSystemsList")
private final List<MommyInterfaceSystem> informationSystems = new ArrayList<MommyInterfaceSystem>();
public void execute() {
...
for(MommyInterfaceSystem s : informationSystems) {
...
s.gatherInformation();
...
}
...
}
}
And now i want to test the results of this process! And here we arrive the my problem.
I wrote a simple unit test to execute the process of gathering information. This process works and it is fine.
I wrote many test for this process and it works greats but if i want to mock an external system (because i want to predefine the return value) it fails...
If i call the gather bean directly (not over the util:list...it works...but then the other actions like analyze or store won't get called...).
I have to do something like this:
If AnotherSystem of informationSystems is calling the "gatherInformation" method of - it is gonna call another method (let's call it "doCall").
And i want to mock this method. The method doCall.
All should be the same, except this method (doCall). Here i want to return a predefined Object.
Sry for this bad explanation, my english is damn bad...but i hope you will understand my problem :/
here i can list what i tried...
i tried to get the system from the list with reflections and replaced it with a mock...the result is a nullpointer exception because of missing autowired beans...
I autowired the bean directly and tried to mock it:
Mockito.when(anotherSystem.doCall(Mockito.anyString()).thenReturn(data);
I tried to create the object with EasyMock.mock...also failed
I didn't try to create a xml context to override the bean definition with own bean, because the system contains many other method which get called...and...yeah...pity...

Passing state to CDI-container-managed beans

I'm using Spring for this project, but I've had the same problem with Guice as well.
Basically, I have functionality that requires both stateless helpers and state data to operate on.
public class AwesomeDoer {
#Inject
private Helper helper; //stateless
...
public void doAwesome(int state) {
helper.help(state)
}
}
This looks pretty good, until doAwesome has 5 parameters and is being called 1000 times, but 3 of the arguments are the same value every time while a fourth argument might change only a handful of times. Changing the appropriate parameters to fields is the obvious solution. However, this requires you to sacrifice either the CDI management of this class, or else you have to have an initializer or setters to fill in the state after Spring does its thing.
I've usually gotten around this by creating a factory managed by Spring, ie
public class AwesomeFactory {
#Inject
private Helper helper;
public AwesomeDoer getAwesomeDoer(int state) {
return new AwesomeDoer(helper, state);
}
}
But again, this means that my AwesomeDoer is no longer being managed by Spring, and it requires me to write yet another layer of non-business logic. It's also easy to imagine this approach leading to the creation of an AwesomeFactoryFactory, etc, which always makes me die a little on the inside.
So does anybody have a cleaner way of doing this?
You can mark your bean using #Configurable from Spring and create it using new AwesomeDoer and passing the parameters in your constructor. #Configurable makes you create the bean on demand and the bean will be managed by Spring to fire the injections like #Autowired.
More info: Create a bean using new keyword and managed by Spring, check the section at the bottom.

Using guice for a framework with injected classes, proper way to initialize?

I'm trying to write a framework where arbitrary bean classes are injected with classes from my API, and they can interact with both those classes as well have triggered callbacks based on defined annotations. Here's an example bean:
#Experiment
static class TestExperiment {
private final HITWorker worker;
private final ExperimentLog log;
private final ExperimentController controller;
#Inject
public TestExperiment(
HITWorker worker,
ExperimentLog expLog,
ExperimentController controller
) {
this.worker = worker;
this.expLog = expLog;
this.controller = controller;
}
#SomeCallback
void callMeBack() {
... do something
log.print("I did something");
}
}
I'm trying to use Guice to inject these beans and handle the interdependencies between the injected classes. However, I have two problems:
One of the classes I pass in (HITWorker) is already instantiated. I couldn't see how to move this to a Provider without significantly complicating my code. It is also persistent, but not to the Guice-defined session or request scope, so I am managing it myself for now. (Maybe if the other issues are overcome I can try to put this in a provider.)
More importantly, I need a reference to the other injected classes so I can do appropriate things to them. When Guice injects them, I can't access them because the bean class is arbitrary.
Here's some really bad code for what I basically need to do, which I am sure is violating all the proper dependency injection concepts. Note that hitw is the only instance that I need to pass in, but I'm creating the other dependent objects as well because I need references to them. With this code, I'm basically only using Guice for its reflection code, not its dependency resolution.
private void initExperiment(final HITWorkerImpl hitw, final String expId) {
final ExperimentLogImpl log = new ExperimentLogImpl();
final ExperimentControllerImpl cont = new ExperimentControllerImpl(log, expManager);
// Create an experiment instance with specific binding to this HITWorker
Injector child = injector.createChildInjector(new AbstractModule() {
#Override
protected void configure() {
bind(HITWorker.class).toInstance(hitw);
bind(ExperimentLog.class).toInstance(log);
bind(ExperimentController.class).toInstance(cont);
}
});
Object experimentBean = child.getInstance(expClass);
expManager.processExperiment(expId, experimentBean);
// Initialize controller, which also initializes the log
cont.initialize(expId);
expManager.triggerStart(expId);
tracker.newExperimentStarted(expId, hitw, cont.getStartTime());
}
Am I screwed and just have to write my own injection code, or is there a way to do this properly? Also, should I just forget about constructor injection for these bean classes, since I don't know what they contain exactly anyway? Is there any way to get the dependencies if I am asking Guice to inject the bean instead of doing it myself?
For context, I've been reading the Guice docs and looking at examples for several days about this, to no avail. I don't think I'm a complete programming idiot, but I can't figure out how to do this properly!
Your "experiment" seems to be something like a "request" in the sense that it has a defined lifecycle and some associated stuff the experiment can pull in at will.
Therefore I think you should wrap all that into a custom scope as described in the docs about Custom Scopes. This matches your case in several points:
You can "seed" the scope with some objects (your HITWorker)
The lifecycle: do "enter scope" before you setup the experiment and "exit scope" after you finished your work.
Access to "shared" stuff like ExperimentLog and ExperimentController: Bind them to the scope. Then both the framework and the experiment instance can simple #Inject them and get the same instance.

Infinite loop when using wicket-guice

im using wicket since a couple of months now and i started to evluate wicket-guice recently.
So im quite a guice noobie :)
Every page got a ServiceClass (lets call it DoService) which manages a number of Objects (i.e. User) ...
Those objects also got an reference to that ServiceClass for some reasons.
public class page ... {
#Inject
private DoService doService;
}
public class DoService ... {
private Collection<User> ...
}
public class User {
#Inject
private DoService doService;
}
Im not quite sure, but i think the following exception occurs cause of the circular references of dependencies though i thought guice manages this all by itsself.
Whatever.....if you need more information to understand my problem pls ask :)
Thanks in advance
java.lang.StackOverflowError
at java.lang.reflect.InvocationTargetException.<init>(InvocationTargetException.java:54)
at WICKET_....DoService$$FastClassByCGLIB$$ce256f9.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.apache.wicket.proxy.LazyInitProxyFactory$CGLibInterceptor.intercept(LazyInitProxyFactory.java:317)
at WICKET_....DoService$$EnhancerByCGLIB$$d1f8934e.rollback(<generated>)
at WICKET_c....DoService$$FastClassByCGLIB$$ce256f9.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
......
I think your design is incorrect: a domain object should not contain references to services. You indeed have a circular dependency.
What Guice does here is to create a new User instance for every DoService instance and a new DoService instance for every User instance. I don't think that's what you want to archive here (apart from the questionable design).
There are several ways around this issue:
Use appropriate Providers in your module
Use singleton scope in guice
Use guice only for one of these instanciations. Have one object create the other and supply itself to the other's constructor for back-reference.

Categories