Giter Club home page Giter Club logo

Comments (8)

kelunik avatar kelunik commented on July 18, 2024 2

@casid This isn't about methods or class files being too long, but rather the constant string size limit of Java, which is 65535 bytes, which is quite low for larger templates that don't contain variables.

I've implemented a fix in #26 and classified this as a bug rather than an enhancement.

from jte.

tomholub avatar tomholub commented on July 18, 2024 1

Definitely - that's what I will be doing (splitting it up). However I didn't expect to run into such limit - you never know what use cases others will run into.

For myself, I wanted to have an all-inclusive "samples" page that has all sorts of html elements or components from our html templates that have not yet been transformed into usable jte components. It's like a repository for our devs where they could go to /samples on a dev build and see all of their choices, find the component that best fits their scenario, and turn that into a jte template.

It's not exactly a production scenario so I'll do something else. But others may be in a different situation.

from jte.

casid avatar casid commented on July 18, 2024 1

We're also using this for our styleguide - to display the jte code 'as is' and below the rendered result.

public static Content importFile( String relativePath ) {
   return templateOutput -> templateOutput.writeContent(getFileContent(relativePath));
}

public static String importFileEscaped( String relativePath ) {
   return getFileContent(relativePath);
}

In the styleguide jte template we'd use something like this:

<h2>Code</h2>
${importFileEscaped("jte/tag/styleguide/sample1.jte")}

<h2>Result:</h2>
@tag.styleguide.sample1()

For your usecase you might want to use something like:

<h2>Code</h2>
${importFileEscaped("jte/tag/styleguide/sample1.jte")}

<h2>Result:</h2>
${importFile("jte/tag/styleguide/sample1.jte")}

from jte.

tomholub avatar tomholub commented on July 18, 2024 1

For myself, I made it a static file and later I'll use importFile as you suggested.

You can leave this issue open for a while first - if others have the same issue, they may leave a note here.

from jte.

casid avatar casid commented on July 18, 2024 1

Alright, will do that. Good luck and let me know if you run into any problems with this approach.

from jte.

casid avatar casid commented on July 18, 2024

Hey @tomholub,

thanks for reporting! I always thought this to be a rather theoretical issue :-) I haven't come close to that limit yet.

In your case, would it work to extract common parts into their own reusable tags? Or is it really a super big file to include?

At work, we have the usecase to include generated css/js files, that are pretty big and don't contain any jte logic at all (they are generated by webpack).

Edit: We use a class like this to load those. Maybe this would be useful to add to jte itself? Would this solve your usecase?

public class JteImportFiles {

   private final Path                          _root;
   private final boolean                       _checkModificationTimes;
   private final ConcurrentMap<String, Long>   _modificationTimes = new ConcurrentHashMap<>();
   private final ConcurrentMap<String, String> _fileContents      = new ConcurrentHashMap<>();

   public JteImportFiles( Path root, boolean checkModificationTimes ) {
      _root = root;
      _checkModificationTimes = checkModificationTimes;
   }

   public String getFileContent( String relativePath ) {
      if ( _checkModificationTimes && hasChanged(relativePath) ) {
         return _fileContents.compute(relativePath, ( k, v ) -> loadFileContentFromDisk(k));
      }

      return _fileContents.computeIfAbsent(relativePath, this::loadFileContentFromDisk);
   }

   private long getLastModified( Path file ) {
      return file.toFile().lastModified();
   }

   private boolean hasChanged( String relativePath ) {
      Long lastResolveTime = _modificationTimes.get(relativePath);
      if ( lastResolveTime == null ) {
         return true;
      } else {
         long lastModified = getLastModified(_root.resolve(relativePath));
         return lastModified != lastResolveTime;
      }
   }

   private String loadFileContentFromDisk( String relativePath ) {
      try {
         Path file = _root.resolve(relativePath);
         _modificationTimes.put(relativePath, getLastModified(file));
         return Files.readString(file, StandardCharsets.UTF_8);
      }
      catch ( IOException e ) {
         throw new UncheckedIOException(e);
      }
   }
}

from jte.

tomholub avatar tomholub commented on July 18, 2024

Thanks! That looks good to me. More generally, I could imagine some folks running into this, then silently walking away thinking jte is "not mature enough". So even if there is a way to work around, I'd recommend to see if this can be addressed in the codebase itself 👍

from jte.

casid avatar casid commented on July 18, 2024

Splitting the generated classes would be pretty hard to do. The entire state of the render() function would have to be passed to the other class. For instance:

!{var x = "foo";}

<%-- Split happens here --%>

${x}

This is stuff the jte compiler isn't aware of, since it simply delegates the generated class to javac.

It would also not help in your example, since there one single String exceeds the limit. One option would be to load all constant Strings from an external location. However, this would slow down template loading, plus, it would prevent the JVM from String inlining. When I did some benchmarks with this, I noticed that write("foo"); is faster than write(CONSTANT). It would be nice if jte supported this, but it would bring some tradeoffs with it in other places. And I haven't come across a situation when it was really needed.

That being said, would it help to add the ability to import file contents in templates to the jte core? Like the JteImportFiles? Or did you end up with an entirely different solution?

from jte.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.