Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hard-coded uses of src/main/webapp preclude any other project layouts from working #23829

Open
beamerblvd opened this issue Oct 25, 2020 · 4 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@beamerblvd
Copy link

I'll outline a description of the precise problem here, but if you're looking for a deep-dive on exactly how I arrived here, including sample code, take a look at this Stack Overflow post.

In Java Maven projects, the "default" layout (and what most projects use) is src/main/java, src/main/resources, src/test/java, and src/test/resources. However, those are only defaults, and nothing prevents a team from using a different layout. The following configuration supports the layout source/production/java, source/production/resources, source/test/java, and source/test/resources:

    <build>
        ...
        <sourceDirectory>source/production/java</sourceDirectory>
        <resources>
            <resource>
                <directory>source/production/resources</directory>
            </resource>
        </resources>

        <testSourceDirectory>source/test/java</testSourceDirectory>
        <testResources>
            <testResource>
                <directory>source/test/resources</directory>
            </testResource>
        </testResources>
        ...
    </build>

The maven-war-plugin has a similar default: It looks for web application resources in src/main/webapp. However, once again, this is just a default, and it can be configured using <warSourceDirectory>:

    <build>
        ...
        <plugins>
            ...
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.1</version>
                <configuration>
                    <warSourceDirectory>source/production/web</warSourceDirectory>
                    ...
                </configuration>
            </plugin>
            ...
        </plugins>
        ...
    </build>

A problem arises in the fact that Spring Boot hard-codes src/main/webapp in several places throughout the code, which makes it impossible to use a layout which uses a different directory structure for web resources.

I've contributed to Spring before (it's been many years), so I'm willing to work on a pull request to address this problem, but I need some guidance first. I need to know things like: Where would this get configured (spring-boot-maven-plugin? somewhere else?)? How do I get that configuration in those places in code? Perhaps other things that I don't yet know that I need to know.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 25, 2020
@beamerblvd beamerblvd changed the title Hard-coded uses of src/main/webapp precludes any other project layouts from working Hard-coded uses of src/main/webapp preclude any other project layouts from working Oct 25, 2020
@mdeinum
Copy link
Contributor

mdeinum commented Oct 26, 2020

Looking at the hits you found, most of them are in integration/smoke tests for the framework itself. There are 2 that might be troublesome (well actually 1 as the other is configurable).

The one in @WebAppConfiguration defaults to src/main/webapp but can be overridden, the one in the JspTemplateAvailabilityProvider will fallback to src/main/webapp and that might need to be polished/made configurable.

Update (1)
After trying to create a demo to show a possible workaround it appears the main issue is with the detection of a valid document root in the DocumentRoot class. When not a war or exploded war it will only look into 3 default directories (see here).

Not sure if the same logic should be applied in the JspTemplateAvailabilityProvider as that checks the existence of JspConfig to delegate to the container or use the default src/main/webapp directory.

Update (2)
As a workaround for running from the command-line or IDE, a TomcatContextCustomizer can be added to set the proper docBase for this case

@Bean
public TomcatContextCustomizer docBaseCustomizer() {
  return new TomcatContextCustomizer() {
      public void customize(Context context) {
          File root = new File("source/production/webapp");
          if (root.exists() && root.isDirectory())  {
              context.setDocBase(root.getAbsolutePath());
          }        
      }
  };
} 

The drawback is that this adds another location to set the proper docBase next to the one in the pom.xml.

Update (3)
After some more digging it appears that there is a ConfigurableServletWebServerFactory.setDocumentRoot. There is also a ServletWebServerFactoryCustomizer which already binds properties from the ServerProperties to the ConfigurableServletWebServerFactory. If the ServerProperties would also expose a document-root property it could be set through the customizer. Then in a maven or gradle build, you could process the application.[properties|yml] to add the proper value to that property.

Setting the value would only need to be done if the passed in path is a directory and exists (basically the same check that is done in the DocumentRoot class when processing the default locations. It might be worthwhile to add a warning when the location is going to be ignored. (Like when deployed to a server or when running the packaged war).

@philwebb philwebb added the for: team-attention An issue we'd like other members of the team to review label Oct 26, 2020
@philwebb
Copy link
Member

See #12859 for more background

@philwebb philwebb added type: bug A general bug and removed for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged labels Oct 28, 2020
@philwebb philwebb added this to the 2.2.x milestone Oct 28, 2020
@larsgrefer
Copy link
Contributor

If JspTemplateAvailabilityProvider could be modified to use javax.servlet.ServletContext#getResource in order check if a given jsp file exists, the only other usage would be the configuration of the embedded servlet-container itself.

For configuring said servlet container, org.springframework.boot.web.servlet.server.DocumentRoot#getCommonDocumentRoot is only used, if no war packaging can be detected. So it's used for either jar-packaged applications or applications that aren't packaged at all, like unit-tests run by Maven/Gradle or when the application is started directly from an IDE.

I support the suggestion to make the webroot(s) configurable using a property. The Spring Boot Maven and Gradle plugins could then set this property to the correct value when executing the application or its tests.

For jar-based applications, it might also be a nice feature to be able to configure a webroot.

#17233 might add some more background about what is (or should be) considered as web root under different deployment and packaging options.

@philwebb philwebb modified the milestones: 2.2.x, 2.3.x Dec 16, 2020
@wilkinsona wilkinsona modified the milestones: 2.3.x, 2.4.x Jun 10, 2021
@wilkinsona wilkinsona modified the milestones: 2.4.x, 2.5.x Nov 15, 2021
@wilkinsona wilkinsona modified the milestones: 2.5.x, 2.6.x May 19, 2022
@philwebb
Copy link
Member

I did a bit of digging on this one and I think we'll perhaps need to revisit the fix for #12805 (solved by PR #12859 in Boot 1.5). Perhaps we can make the RunMojo set a system property that the JspTemplateAvailabilityProvider can pick it up.

It's a bit tricky because currently RunMojo doesn't know about the Maven war plugin.

@philwebb philwebb added for: team-meeting An issue we'd like to discuss as a team to make progress and removed for: team-meeting An issue we'd like to discuss as a team to make progress labels Jun 21, 2022
@philwebb philwebb self-assigned this Jun 22, 2022
@wilkinsona wilkinsona modified the milestones: 2.6.x, 2.7.x Nov 24, 2022
@philwebb philwebb modified the milestones: 2.7.x, 3.1.x Nov 8, 2023
@wilkinsona wilkinsona modified the milestones: 3.1.x, 3.2.x May 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

6 participants