Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
hardyp180
Active Contributor

Dustbins in Las Vegas – Part 2

You are probably familiar with crime shows on TV like “CSI : New York”. I were to try and describe TECHED 2015 in a similar fashion it would be “CDS : Las Vegas”. The so called “CDS View” was front of stage the entire time, with UI5 standing behind it, waving over its shoulder, and HANA standing in the background trying to get some attention. This blog is just a list of the notes I made from various sessions, hopefully in a logical order, but possibly not.

I know everything changes; everything changes; now I know what I like about You

We will start with the minor things about CDS views and then work our way up. A CDS view arrived on the scene with ABAP 7.4 which the vast amount of SAP customers clearly are not on yet based on a show of hands at various speeches – and the SAO speakers are always shocked, as they have had this for years and so are amazed when real people in the real world are not using such technology. I think my company won’t upgrade till ECC 6.0 goes out of support in 2025.

Anyway, a really big thing was made about the fact that in the names you give to CDS Views you can use “Camel Case”. What is that you may ask? A Camel has been murdered and you are a famous detective trying to work out who committed the crime. Or, possibly, it is naming things in the style of SalesOrderItem as opposed to SALES_ORDER_ITEM. Languages like Java have always used names like that and I think SAP were getting jealous. I am all for making code easier to read but I think you are between a rock and a hard place here.

In 7.5 the generation (creation) of CDS views in ABAP in Eclipse is a lot better e.g. the lines at the top which you previously had to type in manually are generated for you.

Since CDS views are supposed to be the core of everything now it is possible to call and AMDP from inside a CDS view.

When playing in the Web IDE and trying to view the representation of a CDS view, you can get a mockup of the Firori Launchpad with a tile showing your new application. What use this is I have not a clue.

Now, since a CDS view (which is a model in the MVC sense) is the basis for generating a Fiori application you can put a whole bunch of “annotations” inside it, which seem a lot like view related data to me but I am assured it is not, such as can the UI allow the user to search on the data. If you put an annotation like @search in the CDS view then, yes they can, but you also have to specify before each field can it be searched, and the “fuzziness” actor for the search.

In fact what we were shown looked a lot like how you set up the ALV back in 1999 – annotations for which position a field should appear in the UI, can it be totalled and other UI specific things.

One other annotation which reflects the new world is you can say how important a field is – that way if the report appears on a phone the less important fields get hidden due to the lack of room.

I am a Model, you Know What I Mean

James Wood was sitting next to me and asked me – “Should all this information go in the model?”

It did seem odd, I would have thought a model just knows about the data and business logic, the purpose of a view was to decide how to display it to a user, which is why you can have various views of the same model. From a technical perspective all the annotation data goes into a separate file, on the grounds that if you expose the data to some consumers outside the SAP system don’t care about it i.e. ones that will not display the data.

Some years back, it took me a while to get to grips with the “model view controller” concept where each one of the three components does a separate job. Just to confuse things SAP has decided that the data model is going to be called a view i.e. a CDS view. This is because of the historical SE11 data dictionary definition of a database view, which a CDS view evolved out of. Yesterday someone told me that they went to a talk where someone from SAP was talking about “System Landscape Transformation” and said “This is not be confused with System Landscape Transformation”. A redundant warning clearly, who would make such a mistake? It is like the joint product from SAP and Microsoft called “Duet” which is a totally different product from the old one, also called “Duet”.

Anyway, so the data model is called a view in SAP terms. OK we can live with that. What is puzzling from some perspectives is all the “annotations” you can put in the CDS view giving instructions to the UI i.e. the sort of thing you would normally expect the view to take responsibility for. In addition you have a list of commands (actions) you can add to the CDS view which will correspond to the buttons that will appear on the screen, sort of like the icons at the top of the screen when you run an ALV report e.g. export data to excel or whatever. In a minute we will see this is sort of a controller like function, in the definition named “view” which is in fact a model.

Now, SAP want to have a common programming framework for both transactional and analytic applications and the CDS view plays a core role in this. Traditionally a database view was what it said on the tin – a view of the data, so you can have a look at that data and analyse it. Now we can make a CDS view into a transactional view by writing an annotation at the top to say it is a “#BUSINESS_OBJECT” and another one saying it is write enabled.

This generates a BOPF definition, the sort of thing you would normally set up using transaction BOB. Then you can in fact use the BOB transaction to add in business logic to the generated BOBPF object to perform data validations, fill in derived fields, and – as alluded to earlier code the logic needed for the actions (commands the user can do during the transaction). The list of actions themselves are listed in the CDS view and then get automatically generated in the BOPF entity.

I then got utterly confused, as it turns out you need another CDS view, this time called a consumption view, which looked the same as the first one to me, but had lines in it saying you could create / read / update / delete instances of the object. The two CDS views and the BOPF entity all fit together somehow.

The other day a German gentleman was arguing with me in relation to the BOPF chapter in my book, about the fact that when I was defining a model class I had it fill in the texts for things like sales organisation, material name and so forth. His position was that sort of thing had no place in the model; it was purely a UI function. So I was fascinated as to what SAP’s position on this was. In turns out that in the CDS view you add an annotation to say where to get the text name from. That makes sense to me as you are in effect coding a join between say MARA and MAKT and saying you want both MATNR and MAKTX in your data model.

However just to be contrary, at the Fiori Café yesterday I was arguing with a German guy from SAP, arguing the opposite position I usually take, saying that the texts had no place in the model and should live in the view. He managed to convince me otherwise, which is not surprising as that was my real opinion in the first place.

Next comes the big change in 7.5 – in the transactions we are used to you either back out or save the new or changed data. You cannot usually save the record to the database in a draft state with 10% of the fields filled out. However in the new SAP world where you are most likely on a mobile device where the connection to the back end drops in and out like a yo-yo, we now have the concept of a draft document. I fill in a few fields of the sales order, it gets saved to the database as I go along (I think) as a draft, and then my connection drops out, an hour later I can get back online on another device, I fill in the rest of the fields and press save, and the draft gets converted into an actual bona fide database record. In the BOPF generated classes you have methods like CREATE_DRAFT, COPY_DRAFT_TO_ACTUAL and LOCK. I am not yet sure how much of the logic is generated for you, I imagine most of it and then you can add anything extra you might need.

You may have heard of “Project Objectify” on SCN, created due to the failure of SAP to create a set of business objects representing sales orders, deliveries, purchase orders etc. To be more exact SAP has tried with SWO1 definitions, and BAPIS and the like, but you don’t have a class like CL_DELIVERY with life cycle methods and methods like GOODS_ISSUE.

The claim from SAP is that in S/4 HANA they will delivery precisely that. For each business object there will be a CDS view linking the header with the items, and having actions like goods issue. That sounds too good to be true, and has been promised before, we shall see.

Like a Dream, a life, a reason everything ABAP must change

This morning who should be in the lift with me but Karl Kessler from SAP who writes the “under development” column for SAP Insider magazine. I then went to his two hour talk on the future of ABAP.

The first point that came up was that although ABAP 7.5 was released on Tuesday in time for TECHED it wasn’t really, you still cannot download it from the service marketplace. It is aimed at BW initially, and then round about the first quarter of 2016 we will have EHP8 which will delivery ABAP 7.5 to ERP systems. You also need Kernel 7.45 for ABAP 7.5, and that Kernel is not released yet either.

Karl asked the audience how many were using 7.4 already, and based on the show of hands it was virtually nobody, so maybe it is a trifle premature to talk about 7.5, but it is as interesting to me as it gets.

As we know virtually all HANA tables are column based, but when you look at the definition in SE11 you can see there is a radio box to make the table row based. I wondered about this, apparently it is more efficient to have some customising tables as row based.

Next came a list of new features in ABAP 7.5, the SAP examples all look like <X> = (A – B) with no semantic meaning whatsoever, which makes it difficult to get your head around what the new feature does, but after a while I think I get it.

For example you can programmatically generate an internal table by lopping over another internal table and performing calculations on the fields in the source table to generate fields in the target table.

We now have a dynamic “move corresponding” feature where the source and target structures are not known until run time. Also you can use statements TYPE OF and CASE based on the nature of a variable e.g. if it is a string do this, if an integer do that. I presume that is aimed at dynamic data objects such as field symbols.

When it comes to class based exceptions they can now raise a T100 error message before propagating themselves, that message does nothing (I think) it is like in a function module where you say RAISE EXCEPTION SUCH_AND_SUCH WITH MESSAGE etc. and the message is only output if the exception is not handled, to prevent a short dump. This also enables a “where used” search for the error message, so you can hunt down the source of the problem. I thought the idea was a class based exception could contain a load of information about where it was raised and in what circumstances, but anyway that is the new feature. I like exceptions which inherit from CX_NO_CHECK so in the unlikely event of one of my exceptions not getting caught somewhere higher up the food chain, an error message would be better than a dump.

I knew there was a new class for ALV reports, a successor to CL_SALV_TABLE which is optimised for HANA. The class is called something like CL_SALV_IDA and once again you can have a report in just one line of code. This time there is a method called CREATE_FOR_CDS_VIEW which does what you might expect. The important thing here is that instead of the whole amount of data requested being in an internal table, in memory on the server, all that is in memory on the server is the data that is on the screen. All the grouping and sorting and totalling is done on the HANA database level, and when you press the page down button more data is retrieved.

In database tables we have foreign key relations, but sometimes it is difficult to spot relationships between tables, sometimes it takes the developer a while to work out the relationship between tables all to do with production orders – AFKO / AFPO / RESB etc… or the link between fixed assets and the purchase orders used to buy them. CDS views are designed to make such links more obvious – they are supposed to read as “close to conceptual thinking” as possible. The SQLScript code reads something like “sales_order.customer.address” which represents (to my mind) the link between VBAP,KNA1 and ADRC.

So a CDS view is supposed to be a layer above the database tables, giving meaningful names to field names like AUFNR and RGEKZ. In the S/4 HANA system the SAP developers had created 6400 CDS view as at 22/07/2015. The idea is that ABAP programs should only do SELECTS on the views on this will make them more readable, more like a domain specific language .As a side effect it is then possible to mess about with the underlying tables, if such tables are never directly read. The example given was getting rid of an ITEM_COUNT field in a header table, redundant in a HANA system. The actual example I can think of is the field in EKKO which says the highest item number in EKPO.

I think that in 7.4 a CDS view could have input parameters, but then you could only call such a view from within ABAP if you were on a HANA database. This is no longer the case in 7.5, all databases are fully supported with CDS views with parameters. This is quite important; you want to be able to pass selection criteria into such a database view.

To be clear about this - note that CDS views work on any database, not just HANA so if you have an Oracle database like my company you will be fine. SAP are clearly hedging their bets here, they want all their customers to move to HANA but realise this will not happen overnight.

New York Port Authority Check

The next interesting thing inside a CDS view is the authority check. This is called “data control language” (DCL) and reads something like:-

DEFINE_ROLE (‘MAD_SCIENTIST’)

            GRANT_SELECT

            WHERE (EVIL_LABORATORY’)

            ASPECT PCGF_AUTH(‘EVIL_LABORATORY’, *, ‘03’)

What this means is if you run a report against a CDS view and you don’t have authority in your user master for a certain evil laboratory, then records for laboratories you are not authorised to view will not show up. SAP security people should not be worried, the existing authority objects and roles are unchanged, it is just that ABAP developers no longer need to explicitly code AUTHORITY-CHECKS into reports reading from CDS views. The bad news is that the failure does not show up in SU53, though I imagine that will be sorted out in time.

In 7.4 the CDS view had not yet assumed its role as the be all and end all of everything in the SAP universe, and so there was a clear separation between an ABAP program calling a CDS view (database independent) and an ABAP Managed Database Procedure (HANA Only). Now a CDS view can itself call and AMDP, though this will of course invalidate its database independence if the programmer decides to do such a thing.

There are three parts to doing this, first you need to code a definition in the CDS view itself, which goes something like as follows (I don’t have the exact syntax, this is from memory):-

DEFINE TABLE FUNCTION VILLAGERS_TO_BE_KILLED

WITH PARAMETERS

  VILLAGE_NAME : abap.string

RETURNS

{

  LIST_OF_VILLAGERS : abap.something

}

IMPLEMENTED BY METHOD TO_BE_KILLEDOF CLASS VILLAGERS

Then in your ABAP code you do the following:-

CLASS VILLAGERSDEFINITION.

INTERFACE IF_HDMP_MARKER.

CLASS-METHOD VILLAGERS_TO_BE_KILLED FOR TABLE FUNCTION VILLAGERS_TO_BE_KILLED.

This has to be a static method. You probably have to say what CDS view you are talking about as well, as I said I cannot remember the exact syntax.

The last part is writing the implementation of the method in SQLScript. The code has to start with a list of all ABAP tables you will be reading, te reason given for this is that helps if “anything changes” as the ABAP system has a bit of a blind spot where code written in other languages lives.

Then you call the CDS view by doing a SELECT statement in your ABAP program on the view. You will get a syntax warning telling you this is a statement that will only work on a HANA database, this warning can be suppressed witha Pragma.

Apparently in 7.4 debugging an ADMP was done by using a separate tool to the ABAP workbench (which is ABAP in Eclipse in this case). In 7.5 this has been unified, you can only create/view the SQLScript of ADMPS in ABAP in Eclipse in any case, now you can put in a soft breakpoint, and you can then run the transaction and the debugger will stop inside the database whilst the ADMP is being executed. As I may have said previously debugging inside the database as opposed to the application server is quite spooky.

I thought it was quite funny that Karl Kessler said that writing SQLScript code was no fun at all, copying an existing sample and changing it was far easier. I found that as well in my experiments, the syntax is demanding to say the least; I thought ABAP was bad enough – sometimes demanding spaces between the bracket and the variable, sometimes forbidding spaces – but I did not know when I was well off. It also keeps changing, so if you copy something off the internet or a blog, then it most likely will not compile. In the last demo of the day – also two hours and all about CDS views – the SAP developer from Walldrof wrote some SQLScript and kept getting syntax errors and he could not figure out for the life of him what was wrong even with his colleague (and the audience) making suggestions. In the end he copied some – seemingly identical code – from another working application, and everything was fine.

The next funny thing – which I guessed at in my book but am pleased to find turns out to be true – is that inside SAP there is a contest/race between the team that develop CDS views and the team that improves the open SQL access in ABAP. So if a new feature gets added in a CDS view then the SQL team will go all out to replicate that feature in Open SQL, and vice versa. The guideline from SAP (up till now) had been that you use Open SQL first and then only use a CDS view if Open SQL could not cut it. Now CDS views have been elevated to first class citizens that may no longer apply.

Anyway, the idea is that with each release of ABAP the Open SQL gets closer to the “SQL_92” worldwide standard. In release 7.5 for example you have new options like UNION and UNION_ALL and you can have a dynamic ON statement in your ABAP SELECT statement.

On the SCN assorted people have for a long time been bitching about ABAP in Eclipse dropping you back into the SAP GUI for certain elements you wanted to view or change or create. It seems SAP have taken note and it was claimed this will now happen a lot less (they did not say never). You also get the “ABAPDOC” in Eclipse which is like JAVADOC and is for all the ABAP developers who love documenting their code for external people to read. That happens all the time. For example you can write comments next to the parameters in your function modules and you can generate a lovely HTML document. I would note that in the SAP GUI for a long time you have been able to add a long text into parameters of function modules and methods, but very few people either inside or outside of SAP actually did this.

Custom Code Management

This was a talk about how to use the solution manager tools to identify what custom code is being used, get rid of objects that have not been used for years, and then gauge the quality of the custom code that remains. I think it is common knowledge that 65%+ of custom code never gets executed, as us developers add new things all day long and nothing ever gets deleted.

In version 7.1 of the Solution Manager you have the custom code monitoring cockpit with a nice pretty “city model” where types of custom code as shown as skyscrapers of varying height depending on the amount of custom objects in a category. You can use your mouse to twirl the diagram around if you want.

The idea is that first of all you use transaction CCLM to get everything single custom object in your development system, and then use “usage and procedure logging” and the SQL Monitor (SQLM) to see what actually gets executed in the production system over a protracted period. You then set a filter to say (for example) to flag anything over three years old that has not been used for two years as a potential candidate for deletion.

The speaker noted that UPL informed one customer that a certain Z method was getting executed a billion times an hour (actually a billion, not me exaggerating for once) and obviously nothing needs to get called that often so clearly there was a problem in the code that needed to be sorted. That is the sort of unexpected benefit you get when doing a really detailed analysis of what goes on in your live system.

Once you have flagged the vast bulk of your code as never being used then you can start to use the other tools like the ABAP Test Cockpit to do a whole bunch of static checks on the code quality of the portion that remains.

Next year (Q2 2016) the next version of the Solution Manager comes out (it can run on a HANA database, but does not have to) it will have the “Quality Control Cockpit” which is supposed to help with the second half of this process i.e. improving the custom code that actually gets used.

There is also something called the “simplification database” which I think is going to be some sort of standalone tool to check your custom code for things than will break and/or could be optimised when running in an S/4 HANA system.

Fiori in my Inbox

This is the workflow inbox appearing in a Fiori app on your mobile phone or tablet. It’s quite clearly still being enhanced, it can do most of the things you would expect from the standard SAP transaction, and there are user exits to fill the gaps. You can call up attachments for example, and even jump into the work item in SAP GUI for HTML mode.

There is no offline capability at the moment, but that is on the roadmap.

This Netweaver Business Client is Guilty

This kept jumping between NWBC 5.0 which has been out for a while and NWBC 6.0 which is not out yet. In my humble opinion NWBC 5.0 was a lot better than 4.0 because it shares data with the actual SAP GUI and so knows what my SAP systems are for example. I agree though with the developer on SCN who said it was unusable because you get a third of the icons and menu options you are used to in the SAP GUI at the top of the screen. You can get to the others via a drop down menu but it is painful. That clearly has not changed in version 6.

Anyway version 6 is coming out some point this year, which probably means early next year, or late next year. You will need a 7.5 system so the question is academic anyway since it will probably be about three years till any meaningful amount of companies are using 7.5. If you have 7.5 you can also use the Fiori ESS/MSS in NWBC 5.0 but that would not make any sense.

Version 6 opens up with the good old Fiori launch pad with those nice white tiles. As an aside most of the “user menu” type transaction screens in the SAP GUI in my company (ECC 6.0 EHP5) like the plant managers dashboard also have a screen full of tiles you press on to go to various transactions, but ours looks more like a windows phone - we call the underlying transaction ZMETRO.

The point of NWBC is to have the various different UI technologies be able to open within it, starting with the SAP GUI (apparently controls like in the “Enjoy” transactions in the GUI work a lot better) right through to UI5

.

I noticed on one the slides Web Dynpro was missing from the list of possible UI technologies – may it rest in peace - though the Floorplan manager was there.

We were shown the good old MM03 transaction in NWBC 6.0 and the material number field was acting like the Google search field. You also get side panels (so called CHIPS) for a vast array of SAP transactions, though if you add Screen Personas to the mix they vanish until you write a whole bunch of JavaScript code to get them back.

Adding Fiori apps to the list of possible transactions is of course possible but you need to know the “semantic object” when adding the application, and that is like finding the needle in a haystack. You have to go to the SAP Fiori Apps Library web page and then go on a goose hunt.

UI5

Guess what! You need ABAP 7.5 for this as well! Actually you don’t, it works fine on my 7.02 system, but of course all the fancy new things I was seeing need the latest 7.5 version.

At least it was explained why we should use the Web IDE rather than ABAP in Eclipse. Firstly to get the Web IDE you have to sign up for a HANA Cloud Platform account, something SAP want you to do very much indeed. The next reason stated was that you get code completion for JavaScript and XML in the Web IDE and you “don’t in Eclipse”. That sounds odd to me, Eclipse seemed to be doing code completion when I was coding in ABAP and naturally in Java. Another reason given was the built in testing framework – a unit testing framework and some acronym which I presume lets you look at the finished application. That was not as easy as you might think when I tried the same in Eclipse.

You also get all the templates in the Web IDE. The idea being put forward by SAP here is that using templates is like moving from WRITE statements to the ALV i.e. built in buttons for common tasks like exporting to Excel, and these templates are also supposed to be like the Floorplan manager to give a unified look and feel. Then you can mess about with the generated XML view to change anything you want.

The use of such “smart controls” is supposed to reduce the amount of code by 90%.

Actually in my experience what a lot of developers like about UI5 is the very fact you have to write all the code yourself. But SAP – like IT companies since the nineteen fifties – are still pushing the “not one line of code needs to be written” approach. I don’t know how they can say that with a straight face in front of 10,000 developers all of whom would be out of a jo if no-one needed to write code anymore. You need 7.5 for those templates anyway, so this is years away. The generated application code takes its information from the “annotations” in the CDS view as mentioned earlier. We were shown how a “key user” can press a button and then do a GUIxt type of thing where you can move fields around and rename them and hide and add fields, and then let that be the default view for all the company. The company behind GUIxt sponsored the Demo Jam last night (which was wonderful). I am wondering why they are still in business now Personas is free.

On one of the demonstrations I noticed that the controller was in JavaScript and the view was in XML (naturally the model is in ABAP inside the SAP system). That is the way I was taught to do UI5 by Graham Robinson, it makes a lot of sense to me, as that is a clear separation of the concerns of the MVC. Then in another live demonstration one of the presenters said “you will notice there is no view or controller”. Really? That was just after auto-generating the application.

We were shown the “UI5 Inspector” which runs in a Chrome browser, some sort of free ad-on, for looking at the code behind the controls on the screen, debugging them, and changing them on the fly e.g. changing the icon, making the field wider or what have you.

There is some sort of new release cycle for UI5 where the first year is all about innovation (what I call a beta release) and then you get two years of stability. I think they are talking about the back end here as the JavaScript part seems to change every two weeks. So we have SAP_UI_740 where support ends Q12017, SAP_UI_750 where support ends 2018, SAP_UI_751 starts in 2016, and so forth.

The only OSS Notes that count, are the ones that come in large amounts

This was my last session, it might seem like a dry topic, but everyone was very emotional about this subject. You may have had to implement a specific note in the past and SNOTE does the code changes for you, but you have to do the DDIC changes yourself, and add the text elements for selection screens, and assorted other tasks. For some notes this is so complicated you are told not to bother, wait till you implement the next support stack – the new ABAP editor in SWO1 fell into this category.

One of the banes of my life is that in SAP the accounting entry for goods receipt posting for purchase orders with multiple account assignment happens at invoice time, whereas for a purchase order with only one cost centre it happens at GR time. This breaks one of the four laws of accounting, and as I was an accountant to start off with I have always been horrified about this. So when we found a dormant business function in EHP5 to solve this problem we switched it on as fast as fast can be. Sadly the code was all over the place, must have been written by someone on the first day of the job, mixing up WERKS and BUKRS in the code as in SELECT FROM X WHERE BUKRS = P_WERKS. Thus we got the error message “Company Code 1234 does not exist” where 1234 was in fact the plant.

There was an OSS Note to fix this, so I applied it, and at the bottom it said “this causes problems, fixed in note 123”. So I implemented the next note, which in turn pointed me to another note, which in turn pointed me to another note and so forth. At the end of this chain the final note basically said “this is too difficult, upgrade to EHP 6”. Lovely. That would have been wonderful information at the start of the first note, but now I will have to explain every week for the next ten years (which is when we will upgrade) why this task on my list is still “pending”.

Anyway, that is by the by – the problem generally is that SNOTE cannot currently do everything; the developer has to do some things manually. In the new world SNOTE has been beefed up so that it can do everything a support package can do, even though you are implementing a single note. This is done by creating a transport request, which of course happened anyway during the current process so I don’t see why this is so different but a great improvement nonetheless.

Also we were reminded about the automated note search – transaction ANTS_PANTS or whatever it is called, where you can do a trace on the transaction that causes the problem and you get a gigantic list of possible notes related to every module/table called and then have to guess which one fixes your problem. That is still painful but a gigantic step up from doing the search on the service marketplace. The problem was the search was that if your sales order transaction was broken then searching for “sales order” would not find the fix but searching for “RV45ZZ87” would find it, as that is the INCLUDE that was broken. So you had to know the technical name of what was broken, which of course no-one does. The ANTS_PANTS is a big step up from that.

The End is Nigh

This blog ended up a bit longer than I thought, but I needed to write everything down before I forgot it – the contents are therefore in somewhat of a random order, but at least it was not a series of photographs with no text (as in “look at this lovely place I am in”) or a series of names of people who I met (I did meet a lot of great people, but why would you care?). I am currently in the Double Helix Wine Bar typing up my notes and trying to explain to the bartender what SAP is. A conference with ten thousand people and this hotel is so big none of the staff noticed. The Industrial Fastener conference was next door to ours, which probably made more impact, everyone knows what a fastener is.

I gave a speech myself – about Push Channels – but that will be a subject for a blog of its own. So that is that…..

Cheersy Cheers

Paul 

 

2 Comments