I have a frontend application, that only knows about and communicates with a single backend service. This backend service serves only this frontend app and no-one else. Backend is completely stateless, no user session or response caching.
Backend exposes a few operations, mostly commands that go to external SOA services where serious logic happens. This backend is only a simple adapter so the frontend doesn't have to deal with SOAP webservices, complicated responses etc.
When client normally interacts with the website, frontend calls operations A, B and C - really heavy SOA services.
Then client requests a printout. Printout is a simple pdf. To create it the special SOA service needs to be called. The input to this service is bunch of very specific data and the output is base64 pdf data. To create the input, data from operations A, B and C is necessary. Frontend already has that data since it called the necessary operations before, backend doesn't remember it since it's stateless.
The problem is the input data preparation to call pdf creation service. Which layer should do it? Frontend already has the data needed to create the input, but should frontend really be responsible for something like this?
Backend could potentially do it - in most cases, it could call the operations A, B and C again and prepare the printout data. Redundant calls would have to be made. But what if one of those operations is not idempotent?
Is there any good way to do this while keeping the backend stateless? How are things like that usually done in web applications? It's not 2000 anymore and I know that frontends do a lot more these days, but this is business logic, to me it sounds like something that frontend should not be responsible for. On the other hand I can't see a way to do this in the backend, other than having the frontend send pure responses from A, B and C operations and then backend just assemble those into printout input - but I don't like it.
//edit after @joshp comment
Right now we are sending data from the client - but client assembles printout input himself (setting correct fields, finding correspondence address in list of all adresses and stuff like that). This concerns me, because people are complaining about development complexity, business logic in the frontend and unability to test it (2 ouf of 3 are not really true, but we specialize in backend dev, so it's understandable). Plus we have some custom java libraries to operate on this client model - it's not much, but it's a little advantage.
The other option I mentioned at the end - that the client doesn't assembly response himself, but sends pure responses of A, B and C to the backend - just seems kind of 'artificial' to me, frontend sending back data to component that gave it to him in the first place. I guess it's still better approach than the first one.