Wish [ABMaterial] Request for configurable App and Content folders

stanmiller

Active Member
Licensed User
Longtime User
Request for configurable App and Content folders

The ABMaterial library v1.20 and earlier require the ABM webapp content to be located immediately below a "www" folder on the web server. By convention the files below the "www" folder are assumed to be on the public Internet and accessible by a browser.

However, hosting companies are split on this architecture. Instead of "www", many hosts serve Internet content under the folder "public_html" and yet others provide both "public_html" and "www" for compatibility.

Our host follows the "public_html" convention. We could use a symlink to make "www" an alias for "public_html" but in general these things should be app configurable.

While ABMaterial's content structure should remain distinct, we propose adding two configurable paths where the developer can specify:
  1. The location of the ABM webapp .JAR (Defaults to File.DirApp)
  2. The location of the ABM webapp content (Defaults to Server.StaticFilesFolder?)
Here's a sample folder tree.

1_abm_webapp_jar_content_folders_zps4wsufsqg.jpg


We have three websites hosted under "public_html." Note that DEMO.JAR and JETTY.KEYSTORE are located in a private folder above public_html and inaccessible to the public internet.

Following the example above the configurable ABM app and content paths would be:

AbmDirApp="/usr/home/macthomas/b4j/abmwebapp"
AbmDirContent="/usr/home/macthomas/public_html/macthomasengineering.com/abmwebapp"
 
Last edited:

alwaysbusy

Expert
Licensed User
Longtime User
I've been looking into it over night and it looks like I will be able to do this in 2.0. I have to keep compatibility with the original system (some components like the ABMPDFViewer have internal redirects). The location of the .jar file is not something I can choose while B4J compiles. However, by setting up your develop folders in a certain way, you still can do everything as before. Once you deploy, copy the .jar to the appropriate folder.

Example (no nice graphics as yours, but you'll get the idea ;))

1. Your development environment:

B4X:
K:\
   DATA\
     Ideas\
       ABMaterial\
         StaticFilesFolderDemo\ ' = the MacThomas folder on the production server
           DemoDynamic\
             Files\
             Objects\
                 demo.jar
             demo.b4j
             ...         
           public_html\
             application1.com\
               abmwebapp\
                 css\
                 demo\
                 font\
                 js\
             application2.com\
             ...

2. Your production server

B4X:
usr/
   home/
     macthomas/ ' = the StaticFilesFolderDemo folder on the development env
       b4j/
         abmwebapp/
           demo.jar
           copymewithjars.needs
           jetty.keystore
       public_html/
         application1.com/
           abmwebapp/
             css/
             demo/
             font/
             js/
         application2.com/
         ...

So it has the same structure (folder depths) in your development environment as on the production server with one difference:

In your develop environment, the demo.jar is in \objects (B4J defined) while on the production server it can be anywhere, as long as the depth of the folders match:

DemoDynamic\Objects\
b4j/abmwebapp/

What will be needed to change in the code (it is mostly the same change to MyStaticFilesFolder, but just to be complete):

In ABMShared you will need to create a variable:

B4X:
Public MyStaticFilesFolder As String = ""

In Main:
B4X:
ABMShared.MyStaticFilesFolder = ABM.CreateAbsolutePath(File.DirApp, "../public_html/application1.com/abmwebapp")

In ABMApplication you need to change/add a couple of lines:

In Initialize, change
B4X:
#If RELEASE
   ...
   folders.Add(ABMShared.MyStaticFilesFolder & "/" & ABMshared.AppName & "/images")
   ...
#End If

In AddPage, change
B4X:
PageNeedsUpload.Add(ABM.WritePageToDisk(page, ABMShared.MyStaticFilesFolder & "/" & page.Name & "/", page.PageHTMLName, ABMShared.NeedsAuthorization))

In StartServer and StartServerHTTP2, change
B4X:
ABM.WriteAppLauchPageToDisk(AppPage, ABMShared.MyStaticFilesFolder & "/" & ABMShared.AppName, "index.html", ABMShared.NeedsAuthorization)

In StartServer and StartServerHTTP2, add AFTER svr.Initialize
B4X:
srvr.StaticFilesFolder = ABMShared.MyStaticFilesFolder

In EVERY BuildPage (ABMApplication + every page you create), add
B4X:
AppPage.StaticFilesFolder(ABMShared.MyStaticFilesFolder, ABMShared.AppName)

Additional:

If you are using a download folder (e.g. for a ABMUpload component, you must change the downloadFolder also:
B4X:
Public DownloadFolder As String = ABMShared.MyStaticFilesFolder & "/" & ABMShared.AppName & "/uploads/"

This is the best I will be able to do. The reason it must be set on every page is because internally the ABMaterial class is unique and pages are unaware of an ABMApplication object. If this is ok, let me know and I implement it. Users that do not want to use this do not have to change anything.

Cheers,

Alwaysbusy
 
Last edited:

stanmiller

Active Member
Licensed User
Longtime User
@alwaysbusy

This looks good and is essentially the same I did last week to separate the .JAR and webapp content. The only snag was the dependency of "www" needing to be the parent folder of the content.

I put all configuration items in a module called WEBAPP.BAS. I set the root folder location for the web content dynamically based on a simple File.DirData test. Then substituted WebApp.RootFolder and WebApp.Appname where applicable in the template code. On my development system all content remains under Objects/www as in the examples.

1. WEBAPP.BAS
B4X:
'**********************************************************************************
'*
'* WebApp.bas - Web Application configuration
'*
'*
'**********************************************************************************

Sub Process_Globals

    ' Config
    Private Const WEBAPP_APPNAME="home" As String
    Private Const WEBAPP_INITIAL_PAGE="welcome" As String
    Private Const GOOGLE_ANALYTICS_TRACKID="UA-XXXXXXXX-1" As String
    Private Const DONATION_KEY="XXYYZZXXYYZZ" As String

    ' Holds root folder name
    Private sRootFolder As String

    ' Version
    Private Const VERSION_TEXT="1.0.13" As String

End Sub


'*--------------------------------------------------------------- RootFolder
'*
Public Sub RootFolder As String

    ' If app and data directories the same assume Linux (production server)
    If ( File.DirApp = File.DirData( "" ) ) Then

        sRootFolder="/usr/home/macthomas/public_html/macthomasengineering.com/abmwebapp/www/"

    ' Development in Windows
    Else

        sRootFolder="C:\Data\Mte\Todd\37_ABM~1\Mte1\Objects/www/"

    End If

    Return  ( sRootFolder )

End Sub

'*----------------------------------------------------------------- AppName
'*
Public Sub AppName As String
    Return ( WEBAPP_APPNAME )
End Sub

'*--------------------------------------------------------------- InitialPage
'*
Public Sub InitialPage As String
    Return ( WEBAPP_INITIAL_PAGE )
End Sub

'*--------------------------------------------------------------- VersionText
'*
Public Sub VersionText As String
    Return ( VERSION_TEXT )
End Sub

2. MAIN.BAS - srvr.StaticFilesFolder changed to WebApp.RootFolder
B4X:
Sub AppStart (Args() As String)

    Mtelog.Start
    Mtelog.Console( "MTE Website v" & WebApp.VersionText )
    Mtelog.Info( "File.DirApp=" & File.DirApp )
    Mtelog.Info( "WebApp.RootFolder" & WebApp.RootFolder )
    Mtelog.Info( "Server.StaticFilesFolder=" & srvr.StaticFilesFolder )
    Mtelog.Info( "Changing StaticFilesFolder to WebApp.RootFolder ..." )
    srvr.StaticFilesFolder = WebApp.RootFolder  ' <---------------------------------
    Mtelog.Info( "Server.StaticFilesFolder=" & srvr.StaticFilesFolder )

    ' Build the Theme
    ABMShared.BuildTheme("mytheme")

    ABMShared.TrackingID = WebApp.GoogleAnalyticsId ' IMPORTANT Change this to your own Google Analytics TrackingID !!!!!!!

    ' create the app
    Dim myApp As ABMApplication
    myApp.Initialize

    ...

EndSub


3. ABMApplication.AddPage with WebApp.bas config
B4X:
public Sub AddPage(Page As ABMPage)
    Pages.Add(Page.Name)

    Mtelog.Info( "ABMApplication.AddPage: " & WebApp.RootFolder & WebApp.AppName & "/" & Page.Name & "/"  )
    PageNeedsUpload.Add(ABM.WritePageToDisk(Page, WebApp.RootFolder & WebApp.AppName & "/" & Page.Name & "/", _
        Page.PageHTMLName, ABMShared.NeedsAuthorization))
End Sub

4. AppPage.StaticFilesFolder

I see the AppPage.StaticFilesFolder method is new.
B4X:
AppPage.StaticFilesFolder(ABMShared.MyStaticFilesFolder, ABMShared.AppName)

Integrating with WebApp.bas it would look like this:
B4X:
AppPage.StaticFilesFolder(WebApp.RootFolder, WebApp.AppName)

5. Folder Depth

...while on the production server it can be anywhere, as long as the depth of the folders match:

In other words, the webapp content has a well defined folder structure. CSS, FONT, JS, and <AppName> are at the same level in the root folder of the webapp content. While the folder structure below <AppName> is also well defined with AppPages and supporting assets. Correct?

Looking forward to 2.0. Thanks for all the hard work!
 
Last edited:

alwaysbusy

Expert
Licensed User
Longtime User
@stanmiller That looks like some well organized programming you do!

If you could just add this as a wish in the feedback app (a link to this forum post for the body suffices), I'll start working on this.

I'm thinking of building a 2.0 version (with the B4JS/ABMXPlay parts removed for now) by the end of this week so if this could be included too, it would be nice.
 

stanmiller

Active Member
Licensed User
Longtime User
...
In Main:
B4X:
ABMShared.MyStaticFilesFolder = ABM.CreateAbsolutePath(File.DirApp, "../public_html/application1.com/abmwebapp")

The new Page.StaticFilesFolder API worked. We're now able place the .JAR and app content in independent folders.

The ABM.CreateAbsolutePath() example above implies that the pathing between the .JAR and content are relative.

Instead we assigned the full path to the content location.

ABMShared.MyStaticFilesFolder="/usr/home/macthomas/public_html/macthomasengineering.com/abmwebapp/www"
 
Top