Custom addon component not found - sap-commerce-cloud

I'm trying to create a component within an addon. Everything works fine during impex process (contentslot, pagetemplate etc.) but it doesn't get rendered when accessing the page.
I've followed these steps but my controller isn't even get called.
#Controller("ConfirmationComponentController")
#RequestMapping(value = ControllerConstants.Actions.Cms.ConfirmationComponent)
public class ConfirmationComponentController extends AbstractCMSAddOnComponentController<ConfirmationComponentModel> {
#Override
protected void fillModel(HttpServletRequest request, Model model, ConfirmationComponentModel component) {
}
}
I've added the component's jsp in "WEB-INF/views/responsive/cms/.." from the addon module but I keep getting this error:
File [/WEB-INF/views/addons/trainingcore/responsive/cms/confirmationcomponent.jsp] not found
P.S.: I've managed to get the component controller to be called, but the getView() is returning a wrong path and that's why the component is not getting called. Any help? Thank you very much:)
Should this component to be created in addon *-items.xml?

What you need to know first
Using addons is a complicated endeavor in hybris. You need to know, that the resources are not used in the addon, but they are copied (during build process) to your storefront, where they are used.
All classes in
myaddon/acceleratoraddon/web/src/
will be copied to:
mystorefront/web/addonsrc/myaddon/
All resources in
myaddon/acceleratoraddon/web/webroot/
will be copied to corresponding folders:
mystorefront/web/webroot/WEB-INF/_ui-src/addons/myaddon
mystorefront/web/webroot/WEB-INF/tld/addons/myaddon
mystorefront/web/webroot/WEB-INF/messages/addons/myaddon
mystorefront/web/webroot/WEB-INF/tags/addons/myaddon
mystorefront/web/webroot/WEB-INF/views/addons/myaddon
That means
That means, that the effective path to your component jsp will not be something like:
/WEB-INF/views/cms/...
but will be something like:
/WEB-INF/views/myaddon/cms/...
The path myaddon will depend on the extension your component is declared in. So if you declare it in trainingcore-items.xml it will be
/WEB-INF/views/trainingcore/...
If you declare it in myaddon-items.xml it will be
/WEB-INF/views/myaddon/...

Related

How to use default constructor in codeIgniter4?

I want to use controller to load directly some models by using default constructor, but CodeIgniter4 was removed __construct method from CodeIgniter4 framework and I got error message Cannot call constructor. please see code below:
public function __construct(){
parent::__construct();
//Do magic task here
}
Instead of CI3 is working by using above code, Can anyone suggest me in CI4?
Thank You for your tips or comments!
Best Regards!
CI4 default controller namespaced CodeIgniter\Controller doesn't have a class constructor. So if you're extending directly from it, parent::__construct() can't be called.
If you really need a constructor for every one of your controller you should modify App\Controllers\BaseController and making your others controllers extending it with the code you provided.
Also if your goal is to execute some code before or after your controller is called you should check out Filters in CI4. They are perfectly designed for this need : https://codeigniter4.github.io/userguide/incoming/filters.html
You can use constructor in CI4 to load models
Add the code in your Controller class and it should work.
protected $userModel;
public function __construct()
{
$this->userModel = new UserModel();//Create a instance of the model
helper('form', 'url');
}

mockito - mock protected method in different packages

I am writing the test case using mockito for a protected method.
public HttpResponse createPostRequest(HashMap<String, String> requestHeaders, String url, String methodName)
{
//some logic
}
my class is in src/main/java and test case is in different package src/main/test.
and am using the following.
Mockito.doReturn(mockHttpResponse).when(userServiceImpl).createPostRequest(Mockito.any(HashMap.class),
Mockito.any(String.class),Mockito.any(String.class));
but it is not working. It is asking to change the method signature to public.
Please help on that.
Thanks.
This seems a configuration problem with your project structure. Your main class is in src/main/java and test class is in src/main/test with one source folder src.
While you could get this to work (setting source folders in buildpath etc.), but most of the time below project structure is used (eg. in spring boot/ maven):
Project-Name
bin
lib
src
main
java
SomeMainClass.java
resources
test
java
TestSomeMainClass.java
resources
This structure has two source folders, one for main (src/main/java) and other one for test (src/test/java). This has the advantage that TestSomeMainClass can access the package private i.e. default member fields of SomeMainClass.
The project structure is src/main/java and src/test/java. but with default modifier not able to mock the method. It is asking to modify the modifier as public

Resharper run configurations

I'm trying to make a reshaprer plugin to add one (or more) configurations, besides executable, static method, project, at resharper's build/run window.
Any guidelines where to start? Or how to access build's context and configure?
Currently examining the JetBrains.IDE.RunConfig, SolutionBuilders etc but one help would be appreciated.
Should this plugin be a SolutionComponent or a SolutionInstanceComponent?
Resharper's sdk help lucks documentation on build/run component.
Thank in advance!
You can extend the available run configuration types by implementing IRunConfig and IRunConfigProvider.
The IRunConfigProvider class needs to be marked as [ShellComponent], and can derive from the RunConfigProviderBase abstract base class. You get to specify a name, e.g. "Executable", a type identifier, e.g. "exe" and an icon ID. There's also the CreateNew method, which will create a new instance of your IRunConfig class, which will be mostly unconfigured, at this point.
The IRunConfig interface doesn't need to marked as a component, and should also derive from RunConfigBase - take a look at RunConfigExe in dotPeek to see an example of how to implement. You should override Execute in order to actually run whatever it is you need to run. You can use the RunConfigContext class passed in to actually execute a process from a ProcessStartInfo, or an IProject - this will execute it either by running the process, debugging it, or something else, such as code coverage or profiling.
For an .exe, this is as simple as:
public override void Execute(RunConfigContext context)
{
context.ExecutionProvider.Execute(GetStartInfo(context), context, this);
}
But for a more complicated example, look at RunConfigMethod.Execute, which uses its own standalone launcher executable, and passes in command line parameters to load the correct assembly and execute the given static method.
Settings are implemented with ReadSpecific/SaveSpecific, and you can provide an editor view model with CreateEditor. You'll need a settings class, something like:
[SettingsKey(typeof (ConfigSettings), ".exe config")]
public class ExeSettings
{
[SettingsEntry(null, "Path to .exe")] public string Executable;
[SettingsEntry(null, "Working directory")] public string WorkingDirectory;
[SettingsEntry(null, "Command line arguments")] public string Arguments;
}
The view for the editor is provided by a WPF control that is displayed in a dialog that ReSharper controls. The view needs to be decorated with the [View] attribute and must implement IView<T> where T is the concrete class returned from CreateEditor. This is how ReSharper will locate the view for the view model returned by CreateEditor. Again, take a look at RunConfigMethodView in dotPeek for some more idea of what's going on (and if you look in the resources, you'll be able to see the XAML itself).

Using Camel Processor as custom component

I want to make a custom camel processor to behave as a custom component.I read it as it as possible from http://camel.apache.org/processor.html - section--> Turning your processor into a full component.
Here the Custom Processor created will have to do the job when i call
someComponent://action1?param1=value1&param2=value2
in the route.
For this i created a sample component using maven catalog.This created Endpoint,Consumer, Producer and Component classes.
The link says that the component should return ProcessorEndpoint which i have done.
So, Endpoint looks as below
public class SampleEndpoint extends ProcessorEndpoint{
// Automatically Generated code begins
public Producer createProducer() throws Exception{
return new SampleProducer(this, processor);
}
public Consumer createConsumer() throws Exception{
throw new UnsupportedOperationException("This operation is not permitted....");
}
// Automatically generated code ends here
//added below to make custom processor work for custom component
public Processor createProcessor(Processor processor){
return new SampleProcessor();
}
}
But, here the code in the processor is not getting executed instead the code in the SampleProducer gets executed.
Here i want the processor to be excuted.How do i do that?
When extending ProcessorEndpoint, the Producer from createProducer() will handle the exchange, i.e. Producer.process(Exchange exchange).
This is why you are seeing SampleProducer being used. But if you wanted to delegate to a processor, you could probably just change your code to be:
return new SampleProducer(this, new SampleProcessor());
My best advice would be to attach a debugger and put breakpoints in your SampleEndpoint, SampleProducer and SampleProcessor methods to see what gets called and when.

Can CDI #Producer method take custom parameters?

I think i understood how CDI works and in order to dive deep in it, i would like to try using it with something real world example. I am stuck with one thing where i need your help to make me understand. I would really appreciate your help in this regard.
I have my own workflow framework developed using Java reflection API and XML configurations where based on specific type of "source" and "eventName" i load appropriate Module class and invoke "process" method on that. Everything is working fine in our project.
I got excited with CDI feature and wanted to give it try with workflow framework where i am planning inject Module class instead of loading them using Reflection etc...
Just to give you an idea, I will try to keep things simple here.
"Message.java" is a kind of Transfer Object which carries "Source" and "eventName", so that we can load module appropriately.
public class Message{
private String source;
private String eventName;
}
Module configurations are as below
<modules>
<module>
<source>A</source>
<eventName>validate</eventName>
<moduleClass>ValidatorModule</moduleClass>
</module>
<module>
<source>B</source>
<eventName>generate</eventName>
<moduleClass>GeneratorModule</moduleClass>
</module>
</modules>
ModuleLoader.java
public class ModuleLoader {
public void loadAndProcess(Message message){
String source=message.getSource();
String eventName=message.getEventName();
//Load Module based on above values.
}
}
Question
Now , if i want to implement same via CDI to inject me a Module (in ModuleLoader class), I can write Factory class with #Produce method , which can do that. BUT my question is,
a) how can pass Message Object to #Produce method to do lookup based on eventName and source ?
Can you please provide me suggestions ?
Thanks in advance.
This one is a little tricky because CDI doesn't work the same way as your custom solution (if I understand it correctly). CDI must have all the list of dependencies and resolutions for those dependencies at boot time, where your solution sounds like it finds everything at runtime where things may change. That being said there are a couple of things you could try.
You could try injecting an InjectionPoint as a parameter to a producer method and returning the correct object, or creating the correct type.
There's also creating your own extension of doing this and creating dependencies and wiring them all up in the extension (take a look at ProcessInjectionTarget, ProcessAnnotatedType, and 'AfterBeanDiscovery` events. These two quickstarts may also help get some ideas going.
I think you may be going down the wrong path regarding a producer. Instead it more than likely would be much better to use an observer especially based on what you've described.
I'm making the assumption that the "Message" transfer object is used abstractly like a system wide event where basically you fire the event and you would like some handler defined in your XML framework you've created to determine the correct manager for the event, instantiate it (if need be), and then call the class passing it the event.
#ApplicationScoped
public class MyMessageObserver {
public void handleMessageEvent(#Observes Message message) {
//Load Module based on above values and process the event
}
}
Now let's assume you want to utilize your original interface (I'll guess it looks like):
public interface IMessageHandler {
public void handleMessage(final Message message);
}
#ApplicationScoped
public class EventMessageHandler implements IMessageHandler {
#Inject
private Event<Message> messageEvent;
public void handleMessage(Message message) {
messageEvent.fire(message);
}
}
Then in any legacy class you want to use it:
#Inject
IMessageHandler handler;
This will allow you to do everything you've described.
May be you need somthing like that:
You need the qualifier. Annotation like #Module, which will take two paramters source and eventName; They should be non qualifier values. See docs.
Second you need a producer:
#Produces
#Module
public Module makeAmodule(InjectionPoint ip) {
// load the module, take source and eventName from ip
}
Inject at proper place like that:
#Inject
#Module(source="A", eventName="validate")
Module modulA;
There is only one issue with that solution, those modules must be dependent scope, otherwise system will inject same module regardles of source and eventName.
If you want to use scopes, then you need make source and eventName qualified parameters and:
make an extension for CDI, register programmatically producers
or make producer method for each and every possible combinations of source and eventName (I do not think it is nice)

Resources