× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



Hello,

I'm not sure that I understand why you use SQL instead of F-specs. Assuming that you mean "embedded SQL", that is... both embedded SQL and F-specs are global to the module. Both of them have a means of saving data into variables that are local to the subprocedure.

don't get me wrong -- there's absolutely nothing wrong with using embedded SQL for your file access. I just don't see how it solves the "there's no F-specs in procedures" dilemna, since it works exactly pretty much exactly the same as F-specs do from a global vs. local point of view.

Using qualified data structures for your database results (whether they come from F-spec native I/O or SQL, either way) would be a good idea, IMHO.

For your #4 note... there's only one LDA per *job*. So, obviously, you can't have a separate LDA for each subprocedure. Consequently, I see no disadvantage to reading the LDA from the global D-specs instead of in a subprocedure.

Are you at risk of two JOBS that use the same service program corrupting each other? Assuming that I can take the word "job" literally (meaning the unit of work that i5/OS calls a "job") then no. Jobs create separate activations from other jobs. This is true of both *PGM and *SRVPGM objects. They'll also have separate access paths to the databases.

In fact, I think it's helpful to remember that a service program (*SRVPGM) is pretty much identical to a regular program (*PGM) in every way. There's really only one difference: a *SRVPGM lets you call all of it's subprocedures independently, and a *PGM does not. In every other way, *SRVPGM and *PGM are identical.

Don't overcomplicate things by thinking of a *SRVPGM as some alien tool. It's just a program where the subprocedures can be called independently -- nothing more, nothing less.

However, if instead of a "job" you really mean that you have two different programs in the SAME job that are calling the same service program, then the answer will depend on your activation group strategy.

Just like a *PGM, one copy of a *SRVPGM can be called by many other programs on the system. If that *SRVPGM isn't stateless, then one program might change something that another program expected to be unchanged.

For example, I once saw an application where a sales rep got a subfile listing all of his customers. He could move the cursor to a given customer and press ENTER to drill down into details for that customer. When he hit F12 from those details, it'd return to the higher-level listing. This was implemented as two programs, one that did the screen logic for the list of customers, and another one that was called to display the details of each customer. A service program named CUSTINFO was used by these programs to get the customer information. CUSTINFO had a "start list" routine that started the list of customers by running SETLL on the customer file. It had a ReadNextCust routine that would use READE to get the next entry. It also had a CustDetails procedure that would chain to a given customer record and get the details. The problem was, the first program (the one that displayed the list of customers) would load one page at a time into the subfile, then at the user's instruction, call the 2nd program. When the 2nd program loaded the customer details, it's CHAIN operation would change the position of the customer file. When the user exited the details screen and hit page down, ReadNextCust would read the record after the CHAIN instead of the record after the last entry that had been loaded into the subfile. This resulted in the paging not working properly.... they couldn't figure it out, so they called me in, and I pointed out the problem. Both the "list of customers" program and the "customer details" program were sharing a single activation of the service program, so the CHAIN, SETLL, and READE were all changing the cursor of the same database file.

I wouldn't exactly refer to that as "corruption". But, it's the sort of problem you run into when you begin using service programs and haven't yet learned to make them stateless. By "stateless", I mean one call to the service program doesn't rely on something to have been "set up" by a previous call to the service program. Or to put it another way, the service program doesn't need to be in a particular "state" when a call is made.

But that situation would never have happened if the two programs were in different JOBS -- the problem only happens when programs in the same job share a service program, and the service program isn't stateless.

As luck would have it, I'm actually planning to publish an article TODAY (assuming the folks over at Penton aren't having technical difficulties) that includes information about how I like to write service programs. I'll post a link when the article is available to the public.



nike@xxxxxxxxxxxxxx wrote:
Hi All,

We have just recently started using service programs and procedures for a
lot of our new development. While a couple of us have some experience, in
many ways we are still winging it.

In a meeting with one of the other programmers, a few interesting
questions came up. Mostly along the lines of 'why does this even
work?'... We have adopted some practices that are working but we are not
100% confident that there is not something ugly waiting to bite us down
the road.

Here are a few of the things we are doing -- If any of them are major
no-nos I would appreciate a heads up:
1 - Because we cannot use F-specs in a procedure (yet) we use SQL for all
data access. One of our programmers mentioned that we were the first shop
he has seen using SQL in service program procedures.
2 - Because SQL host variable names must be unique in a source member, our
service programs use a list of 'global' D-specs for things like Customer
Number (sqlCusn). Any procedure in the service program that uses Customer
number as an SQL parm now uses sqlCusn.
3 - We are grouping related procedures in single members - for example,
there are about 10 or so EDI related procedures in a single source for the
EDI Service Program.
4 - We have a Test and Live environment, with unique library lists. In
normal RPG we would test the LDA to determine the environment, but in
procedures we cannot. We have experimented with adding the LDA to the
'global' D-specs and it seems to work...

Encapsulation is our main concern. Are we at risk of two jobs that use
the same Service Program corrupting each other -- SQLCOD or sqlCusn
overlaps, crossed LDA values, etc?

Sorry for the long post, but sometimes I get scared when things work and I
am not sure I understand why. When I first started coding I was advised
that if your program compiles without error on the first try then scrap
the code and start over...

Let me know your thoughts,
Thanks!
JD




As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:
Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.