We provide web services that'll return informations about a product like this (simplified)
<product>
<id>123</id>
<name>Mobil-home</name>
<pricing>
<price>12</price>
<adults>2</adults>
</pricing>
<pricing>
<price>15</price>
<adults>3</adults>
</pricing>
</product>
Our partner says "Our problem is that in our system we can have only 1 adult count per product". This partner is working with a huge system, and they say that it's a big problem and they can't change anything about it in their side.
So what did we decide ? to explode our results like this
<product>
<id>123</id>
<virtualId>123#2</virtualId>
<name>Mobil-home</name>
<pricing>
<price>12</price>
<adults>2</adults>
</pricing>
</product>
<product>
<id>123</id>
<virtulId>123#3</virtualId>
<name>Mobil-home</name>
<pricing>
<price>15</price>
<adults>3</adults>
</pricing>
</product>
So we created a "virtualId" that concatenate the id and the adults with an #. Technically it's a mess, but we do software for a business, the target is not to make clean software, but to make money.
My solutions are :
I try to make a concept out of it : "In some call I have to call a service class that'll explode our results", and then add this functionality to my web service (even if I'm sure we'll use this only in the case of this partner).
I do 3 dirty lines of code with an ugly (if user == "thispartner")
I add a layer between my partner and my web service that'll do the ugly job
I'm stubborn and I say to my boss "We can't work with them, our systems are not compatible", and then I go to the Pole Emploi.
How do you deal in these cases ?
I think the best technical solution will really depend on your implementation, so it isn't really language-agnostic.
For example, if you use a language with full reflection, like Python, my solution would be to add a database field to the partner list named something like TransformationClass. Then, your web service code would look something like:
output = do_normal_processing()
if partner.TransformationClass is not null:
transformation = construct an instance of the partner.TransformationClass class
output = transformation.transform(output)
return output
(Note: for Python, you can construct an instance based on a classname like this.)
You can then create a source code subdirectory 'clientSpecificTransformations' and dropper-client transformations in there; no need to even recompile or restart anything.
However, IMHO for languages that lack the reflection to do such a thing, you'll end up jumping through hoops, and I'd just write a specific proxy for that client and instruct him to use the proxy's URL. The proxy can just make the exact same request to the original service and then explode as required.
Related
Normally I use Chemspider webservice client (WSDL) with the help of Knime generic web service clients to convert a list of molecule names into a table containing molecular properties (physicochemical prperties,...). Now, Chemspider has suspended its WSDL function and I don't know how to get these data.
I've tried using ChemBL, but the Get request function of uploaded workflows don't work.
Are there any remaining ways (free)?
I myself use pubchempy module for this purpose. It's really easy to handle, and I find it more flexible and easier than chem spider for general use.
I have been trying to break down the differences between the Open Closed Principal and Liskov's Substitution Principal. And the best and most common examples of either use the exact same problem. Finding the Area of a shape class.
They use slightly different means, but effectively solve the same problem with the same solution.
As these are both parts of SOLID, I'm really trying to find a reason to support why both are called out.
I'm looking for an explanation that doesn't work for both.
Thanks.
LSP:
Consumers target an abstraction (e.g. interface) and should not need to know which concrete implementation stands behind the interface. For example, a client (e.g. a DocumentProcessor class) holds a dependency on IDocumentStore. If in V1, you gave it a SqlSeverDocumentStore instance, and then in V2 you gave it a FileSystemDocumentStore, the client (DocumentProcessor) should work without modification. This can be achieved by making sure the contract of IDocumentStore is well defined and that DocumentProcessor, SqlSeverDocumentStore and FileSystemDocumentStore abide by this contract.
The contract means much more than an interface. Having two classes implement the same interface does not mean they abide by the same contract (although they should).
For example, does both implementations support saving documents which are smaller or equal to 20MB? Or does one of them support documents that are at most 10MB? If it is part of the contract that an implementation should support 20MB documents, then all implementations should support this.
OCP:
We should avoid modifying a unit of composition (e.g. a class or a function) after we release it. One way to achieve this is to make the units parameterized. For example, if you have a function (say, ProcessImages) that reads images from the file system, compresses them and then sends them to some web service, you can parameterize this function to accept other functions that are responsible for (1) reading images, (2) compressing them, (3) sending them.
E.g. (in C#):
public static void ProcessImages(
Func<Image[]> getImages,
Func<Image, CompressedImage> compressImage,
Action<CompressedImage> sendImage)
{
//... Orchestrate the operation here
}
And, in the Composition Root:
Action processImages = () => ProcessImages(ReadImages, CompressImage, SendImage);
Where ReadImages, CompressImage, SendImage are themselves functions.
This way, if you want to change how the images are compressed, you will not modify the ProcessImages function. Instead you will create a new compression function (say CompressImageInADifferentWay) and then compose the ProcessImages function in the Composition Root like this:
Action processImages =
() => ProcessImages(ReadImages, CompressImageInADifferentWay, SendImage);
If you apply the OCP in a perfect way, only the Composition Root itself will change.
LSP allows us to achieve OCP. For example, because CompressImage and CompressImageInADifferentWay abide by some contract that ProcessImages knows about, we can replace CompressImage with CompressImageInADifferentWay without modifying ProcessImages.
I've been playing around with this for a while now, and I think, I've - almost - cracked it, but I am still not fully satisfied with my solution.
So, what I want to do, is having a piece of content, a list of items, which would have two views: The standard HTML one, so people can view and edit it; and then a JSON endpoint for other services to consume.
First I thought it's a simple matter of creating two JSP scripts to render the content:
/apps/my-stuff/components/list-page/html.jsp
/apps/my-stuff/components/list-page/json.jsp
However the Apache Sling DefaultServlet seems to be rather ignorant of the json.jsp script.
As a second attempt, I created another script, in /apps/foundation/components/primary/cq/Page/json.jsp which will be actually called, and renders the page, as I expected. However there are a couple of worries/questions regarding this:
First of all, why is this being honoured by the system, and not the one in the more specific place?
The documentation states, that to find the appropriate renderer, first sling:resourceType will be inspected, then sling:resourceSuperType and then, only as a fallback will jcr:PrimaryType checked. However I think this is rather: jcr:PrimaryType, then the DefaultServlet, and then all the other things.
Most worryingly however, I have to admit, this is rather generic, so it'll break all the contnet with jcr:PrmaryType = Page, so that could have some side-effects.
A solution could be creating a new type: ListPage extends Page; and then create a renderer for that in /apps/foundation.... However I have this bad feeling, that might introduce other problems.
So my question is two fold: What is the proper way of doing this, and/or what am I missing from the way the URL -> script resolution is working in AEM/Sling. (Because it seems to be slightly different that described here and here.)
(Obviously I am trying to keep the default JSON renderer for other pages, as that might be needed for other things in the page. I am not even sure, changing this one page won't break the UI for this particular page...)
However the Apache Sling DefaultServlet seems to be rather ignorant of the json.jsp script.
Have you tried renaming your JSP like so: "list-page.json.jsp"?
If you're using AEM 6.3, you should look at Sling model Exporters. They allow you to automatically register a servlet against your Sling Model (that you can create to model your list content). That servlet can generate a JSON representation of the model for you using Jackson.
If you're not using AEM 6.3, I would suggest you create a servlet registered against your resource type and use an additional selector.
#SlingServlet(
selectors = "json",
resourceType = "my-stuff/components/list-page",
methods = "GET")
More information on Sling Servlets can be found here.
I'm following the example of JTreeTable filesystem2 taken from the sun site http://java.sun.com/products/jfc/tsc/articles/treetable2/index.html#updating_the
My problem is that I can't update my model (and then my JTreeTable)...
In fact I create my model, I pass it to the JTreeTable and all work fine...but I need to modify the model...
I've yet answer a similar question, but now I've changed my code, without find a solution.
The problem is when and how I have to call the method fireTreeNodesChanged()...in the example above is used the method getPath() to retrieve information about the root node...but this is a method of File class..not my case...
Does anyone have a link to a simple code which shows how create a TreeTabelModel (with objects as nodes) and how update it?
FileBrowser is a good example of modeling a hierarchical file system as a tree. While its TreeModel is implemented using DefaultTreeModel, an alternative FileTreeModel is shown here. As mentioned in How to Use Trees: Creating a Data Model "the TreeModel interface accepts any kind of object as a tree node."
I have been trying out Service Factory and have run into some problems in regards to long filenames - surpassing the limit in Vista/XP. The problem is that when generating code from the models service factory prefixes everything with the namespace specified. Making the folder structure huge. For example starting in
c:\work\sftest\MyWebService
I create each of the models with moderate length of names in data contracts and service interface. I set the namespace to be MyCompany.SFTest.MyWebservice
After generating code I end up with
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Business Logic
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Resource Access
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Service Interface
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Service Interface\MyCompany.SFTest.MyWebService.DataContracts
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Service Interface\MyCompany.SFTest.MyWebService.FaultContracts
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Service Interface\MyCompany.SFTest.MyWebService.MessageContracts
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Service Interface\MyCompany.SFTest.MyWebService.ServiceContracts
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Service Interface\MyCompany.SFTest.MyWebService.ServiceImplementation
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Tests
Under each of the folders is a project file with the same prefix
c:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Service Interface\MyCompany.SFTest.MyWebService.ServiceImplementation\MyCompany.SFTest.MyWebService.ServiceImplementation.proj
This blows up the recipe as windows can't accept filenames exceeding a specific length.
Is it necessary to explicitly include the namespace in each of the foldernames?
Obviously at some point I might want to branch a service to another location but for the same reason as above might be unable to.
Is there a workaround for this?
I don't know Service Factory so i am not sure if this will help. Anyway: maybe the article Naming a File or Directory from MSDN can help.
Windows API has a maximum length for paths (MAX_PATH = 260). If you want to use longer pathnames you will have to use the Unicode versions of the API by prefixing your paths with "\\?\", i. e. use
"\\?\C:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Service Interface\MyCompany.SFTest.MyWebService.ServiceImplementation\MyCompany.SFTest.MyWebService.ServiceImplementation.proj"
instead of
"C:\work\sftest\MyWebService\MyCompany.SFTest.MyWebService\Source\Service Interface\MyCompany.SFTest.MyWebService.ServiceImplementation\MyCompany.SFTest.MyWebService.ServiceImplementation.proj"
Does Service Factory allow that notation?
We had exactly this problem and we got around it by making our service factory a very thin wrapper around a normal library (that has been marked up with the WCF stuff). This gave us a normally deep project (the factory) and then a stunningly deep wrapper factory (without all that extract interface and logic and what not).
We still have some problems - but mainly in the client side - our servers are for the most part trouble free.