How to override excerpt projection - projection

I have an excerpt defined on a Repo like this:
#RepositoryRestResource(excerptProjection = ListAccountProjection.class)
public interface IAccountRepository extends IRepository<Account> {
When I exec GET /accounts it works like expected.
I have another Projection ShortAccountProjection.
When I exec GET /accounts?projection=short it is simply ignored. So the projection param will never override the exerpt projection from the repo?
When I remove the excerpt from the repo, the projection "sort" works as expected.

If you define an excerpt projection, it is always applied when the collection resource is accessed (/accounts in your case), or the resources is added as _embedded within another resource.
Your ShortAccountProjection will apply only for item resources (e.g. GET /accounts/{id}?projection=short).
Eventually, take a look at Why is an excerpt projection not applied automatically for a Spring Data REST item resource?

Related

Product properties should be inherited for variants but don't seem to load

I'm using a decoration for the product repository to extend the following function by adding streams (dynamic product groups).
public function search(Criteria $criteria, SalesChannelContext $salesChannelContext): EntitySearchResult
{
$criteria->addAssociation('streams');
return $this->decorated->search($criteria, $salesChannelContext);
}
This doesn't seem to work with variants, even tho they're inheriting the properties none of the dynamic product groups based on those properties seem to load. The propertyIds do load for the products so the properties have been added (is default in Shopware).
It seems I was using a decorator for the wrong repository. I extended the SalesChannelProductRepository which means the ProductRepository doesn't change. See source below:
https://stackoverflow.com/a/68232258/14184263
As long as you implement the code above within a ProductRepository decorator it works for both, as SalesChannelProductRepository inherits ProductRepository.
Edit:
There does seem to be a problem with specific rules. See source below: Getting streams from product returns zero results with some rules

How Can I make Spring-MVC #PropertySources load first, before any other configuration

I have a spring-mvc application that is using java configuration, not xml. There are #Configuration annotations sprinkled through several files. In particular, there is a #PropertySources annotation in one file in a class that implements WebMvcConfigurerAdapter. There are two classes which contain an #Autowired Environment variable. One of these classes is itself a #Configuration class, and I would like it to have access to the fully-loaded Environment at the time it runs.
This isn't happening. When this code executes, the Environment is still null. I've tried reordering the #ComponentScan packages, tried moving the #PropertySources annotation, and nothing has helped me load the property sources in time.
I want this to happen first, before any other configuration.
What must I do to make it so?
UPDATE: After trying many things, including the Order annotation, I find the problem seems to be not so much that the #PropertySources are being loaded too late as that a class I have that is derived from org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer is being loaded too soon. Nothing in my code even references this class but Spring is somehow deciding that this, above all other classes, must be initialized first. No amount of messing around with #Order seems to change this. This in spite of the javadocs, which indicate that the behavior I want is the default:
Caveats
Subclasses of AbstractDispatcherServletInitializer will register their
filters before any other Filter. This means that you will typically
want to ensure subclasses of AbstractDispatcherServletInitializer are
invoked first. This can be done by ensuring the Order or Ordered of
AbstractDispatcherServletInitializer are sooner than subclasses of
AbstractSecurityWebApplicationInitializer.
You can use ContextInitializer, catch the moment when Boot prepared its environment and "inject" your property source programmatically as you want.
If you have a ConfigurableApplicationContext then it provides a ConfigurableEnvironment, which contains the propertySources as a list. If you want your PropertySource to rule all above the others than add it as first. If you want to place it to a special position then you can add it before an other, identified by its "name".
public class ConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext ctx) {
// rule over all the others:
ctx.getEnvironment().getPropertySources().
addFirst(new ResourcePropertySource("file:/etc/conf/your_custom.properties"));
// rule over application.properties but not argument or systemproperties etc
ctx.getEnvironment().getPropertySources().
addBefore("applicationConfig: [classpath:/application.properties]",
new ResourcePropertySource("classpath:your_custom.properties"));
// names can be discovered by placing a breakpoint somewhere here and watch
// ctx.getEnvironment().getPropertySources().propertySourceList members,
// each has a name ...
}
}
You can bring into play this class by:
registering it in the application.properties :
context.initializer.classes=a.b.c.ConfigInitializer
or from application start :
new SpringApplicationBuilder(YourApplication.class).
initializers(new ConfigInitializer()).
run(args);
By the way this is a proper way to inject more of your custom properties, like properties coming from a database or a different host etc...
Not that I am an expert in Java config but maybe:
Spring 4 utilizes this feature in its #PropertySource annotation. To
remind you, #PropertySource annotation provides a mechanism for adding
a source of name/value property pairs to Spring's Environment and it
is used in conjunction with #Configuration classes.
Taken from: http://blog.codeleak.pl/2013/11/how-to-propertysource-annotations-in.html
Are you using #PropertySource or #PropertySources?
Have You tried 'order' property for spring bean initialisation?

Defining Symfony Services to maximize maintainability

I'm working on a big domain, for which maintainability is very important.
There are these general workers called ExcelHandlers that implement ExcelHandlerInterface (more on the interface in the ideas section) and basically get an UploadedFile as their input, upload them wherever they want and return the read data as an associative array. Now I have created this base class ExcelFileHandler which does all of these tasks for all excel files given two arguments:
1. The Directory to upload the file
2. the mapping of the excel columns to the indexes of the associative array.
Some ExcelHandlers might have to extend the ExcelFileHandler and do some more processing, in order to get the associative array of data.
The UploadedFile is always passed to the ExcelHandler from the controller.
Now here is the question. Given the generic structure of the ExcelFileHandler how should I define services for specific ExcelHandlers given that some only differ with the original one in the directory to upload the file and the mapping array.
My Ideas:
1. The first approach involves giving the directory and the mapping as the function arguments to ExcelHandleInterface::handle this will make the prototype something like handle(UploadedFile $file, array $mapping, $dir), $mapping and $dir are given to the function as arguments and passed to the handler by the controllers which has the parameters as constructor injections.
2.1 Defining the prototype of handle to be handle(UploadedFile $file), this would require the ExcelHandlers to have knowledge of $dir and $mapping. $dir will always be injected from the constructor.
2.1.1 Foreach individual ExcelHandler in the application, define a separate class e.g: UserExcelHandler, ProductExcelHandler, .... Which extend the ExcelFileHandler and leaves us again with two choices.
2.1.1.1 inject $mapping from outside. e.g:
// in the child class
public function __construct($dir, $mapping){
parent::__construct($dir, $mapping);
}
2.1.1.2 define $mapping in the constructor of the child class. e.g:
// in the child class
public function __construct($dir){
$mapping = array(0 => 'name', 1 => 'gender');
parent::__construct($dir, $mapping);
}
2.1.2 Not to create a class for each separate ExcelHandler and instead define the ExcelFileHandler as an abstract service and decorate with the right parameters to get the concrete ExcelHandler Service with the desired functionality, obviously ExcelHandlers with custom logic must be defined seperately, and to create a uniform code base, $mapping will always be injected from the Container in this case.
In your experience, what other paths can I take and which ones yield better results in the long term?
First of all, it seams as you've already put two separate things into one.
Uploading a file and reading it's contents are two separate concerns, which can change separately (like you said, $directory and $mapping can change case-by-case). Thus I would suggest to use separate services for uploading and reading the file.
See Single responsibility principle for more information.
Furthermore, due to very similar reasons, I would not recommend base classes at all - I'd prefer composition over inheritance.
Imagine that you have 2 methods in your base class: upload, which stores file to a local directory, and parse, which reads excel file and maps columns to some data structure.
If you need to store file in a remote storage (for example FTP), you need to override upload method. Let's call this service1.
If you need to parse file differently, for example combining data from 2 sheets, you need to override parse method. Let's call this service2.
If you need to override both of these methods, while still being able to get service1 and service2, you're stuck, as you'll need to copy-and-paste the code. There's no easy way to use already written functionality from (1) and (2).
In comparison, if you have interface with upload method and interface with parse method, you can inject those 2 separate services where you need them as you need them. You can mix any implementations of those already available. All of them are already tested and you do not need to write any code - just to configure the services.
One more thing to mention - there is absolutely no need to create (and name) classes by their usage. Name them by their behaviour. For example, if you have ExcelParser, which takes $mapping as an argument to a constructor, no need to call it UserExcelParser if the code itself has nothing to do with users. If you need to parse data from several sheets, just create SheetAwareExcelParser etc., not ProductExcelParser. This way you can reuse the code. Also correct naming lets understand the code more easily.
In practice, I've seen when function or class is named by it's usage, and then it's just used in another place with no renaming, refactoring etc. These cases are really not what you're looking for.
Service names (in another words concrete objects, not classes), can of course be named by their purpose. You just configure them with any required functionality (single vs separate sheets etc.)
To summarize, I would use 2.1.2 above all other of your given options. I would inject $dir and $mapping via DI in any case, as these do not change in runtime - these are configuration.

Obtaining path of associated documents in custom model in Alfresco

I have an association in custom model in alfresco as has been mentioned in the post:
How do I associate one piece of content with another in Alfresco?
For properties, to get the name of the property I am using:
var model = document.properties["sc:itemNo"];
How can I obtain the name and path where this image resides in the repository, using JavaScript.
Thanks!
Assuming document has an association named sc:sampleAssoc and there is at least one association exsting for that node, you will get its full qname path like so:
var qNameOfAssocatiatedNode = document.assocs["sc:sampleAssoc"][0].qnamePath;
Be clear though that there may be more than one node at that path.

How to properly set onDeleteAssociationPolicy?

I have custom content type, which has target association. I want to set up a policy, which perform some action, when association is removed. I wrote this policy as I usualy write another policies, but in some reason it does not work. My init() in OnDeleteAssociationPolicy implementation looks like this:
policyComponent.bindClassBehaviour(
QNAME,
PublishModel.pubWebContent,
new JavaBehaviour(this, QNAME.toPrefixString(), NotificationFrequency.EVERY_EVENT)
);
PublishModel.pubWebContent is qname of my custom content type. Now I think when onDeleteAssociation() is called, I should check which association was deleted. But this method is never called after remove association :(. How to set this policy? Should I provide PublishModel.pubMyAssociation instead of PublishModel.pubWebContent (that does not work too)?
I googled a little bit and found working piece of code, which helped me to get that policy worked. The point is to use bindAssociationBehavior instead of bindClassBehavior method. So working binging should look like this:
policyComponent.bindAssociationBehaviour(
QNAME,
PublishModel.pubWebContent,
PublishModel.pubGroupAssociation,
onDeleteAssociation
);

Resources