Live data from Hacker News

An Opinionated Guide to Modern Java, Part 3: Web Development

blog.paralleluniverse.co

131–140 of 168 posts

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#131
post #87

Earlier quoted context omitted.

On the one hand, I've observed that operating system implementers have repeatedly tried and rejected green threads for their pthread implementations (Solaris many-to-many threads and FreeBSD KSEs are both now historical footnotes). In Linux around 2002, there was a new many-to-many pthread implementation called NGPT that was backed by big players like IBM and Intel, until a couple of Red Hat developers (Ulrich Dreppe…

The wheel continues to turn: http://msdn.microsoft.com/en-us/library/windows/desktop/dd62...

IIRC, SQL Server was their first product to use this.

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#132
post #123

Earlier quoted context omitted.

> simpler (because that's what your normal code looks like) Actually, no. My code will always look like the for comprehension be it async or not, because my 'get' methods will always return an Either, Option or some other monadic context to represent the computation succeeding or not. > performs exactly the same (as fibers basically do the same thing, only transparently), Yes, I agree. > c) retains context (like Thre…

When I learned to program (back in the 80s), I learned that if you want to tell the computer to do operation X and when that's done, do operation Y, you just write both statements one after the other. If you're comfortable using for comprehensions to achieve that same goal -- that's great. To me it seems that your code simply replicates what a thread does. If you have a problem with your thread's implementation -- fi…

I wanted to ask you, what about running multiple operations in parallel? I've long been contemplating async/futures vs lightweight threads and yet to have come to a conclusion.

With futures I can say, start operation 1 and operation 2 in parallel, then chain a callback to execute using both pieces of data, saving me some latency of doing the operations serially. How do you do this using quasar? Now that's a trivial example... what about arbitrary dependency trees? This falls out naturally with futures but I don't know of a nice way to do this with lightweight threads. e.g. 1 operation branches off into 5 other parallel operations which then chain some of their own additional callbacks for processing before finally bringing all the results back together, perhaps to form a json response. Does this example make sense?

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#133
I am especially fond of his view on database layers. There's JDBC, which is extremely verbose and needs scaffolding to make it usable, and then ORMS, that will quickly fall apart the moment you actually need to do anything interesting with the database.

The Spring solution to this problem was always my favorite part of their stack: JDBC template removed most of the error prone boilerplate from JDBC, adds a couple of features, and still lets you write SQL directly, which is probably what you should be doing in almost all the cases where a relational database becomes valuable.

I can't wait for shops to start to use Java 8. The removal of so much boilerplate when trying to build functional interfaces should make the Java toolsets move forward very quickly.

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#134
post #2

It's funny. An "Introduction to Modern Java Web Development" sounds like a primer for the Play Framework, Scala, and Akka. Each of the examples looks like the starter documentation for Play, in that you've got your json manipulation, routing, connecting to a database, DI, actors, etc. Java devs-- you seriously owe it to yourself to spend the time investigating and ramping up onto Scala and Play. This is where the fut…

Been there, done that. I switched from Java to Scala and Play. Back to Java 8 and Spring MVC and couldn't be happier to be back.

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#135
post #132
post #123

Earlier quoted context omitted.

When I learned to program (back in the 80s), I learned that if you want to tell the computer to do operation X and when that's done, do operation Y, you just write both statements one after the other. If you're comfortable using for comprehensions to achieve that same goal -- that's great. To me it seems that your code simply replicates what a thread does. If you have a problem with your thread's implementation -- fi…

I wanted to ask you, what about running multiple operations in parallel? I've long been contemplating async/futures vs lightweight threads and yet to have come to a conclusion. With futures I can say, start operation 1 and operation 2 in parallel, then chain a callback to execute using both pieces of data, saving me some latency of doing the operations serially. How do you do this using quasar? Now that's a trivial e…

With lightweight threads you can spawn as many fibers as you like. Creating and starting a new fiber is basically free. You can start fibers and join them, in any dependency tree structure.

Of course, you can keep using futures (what I call semi-blocking API), only futures that block the fiber rather than the thread, when you join them.

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#137

I am especially fond of his view on database layers. There's JDBC, which is extremely verbose and needs scaffolding to make it usable, and then ORMS, that will quickly fall apart the moment you actually need to do anything interesting with the database. The Spring solution to this problem was always my favorite part of their stack: JDBC template removed most of the error prone boilerplate from JDBC, adds a couple of…

Again, just use jOOQ. It's beautiful executed design, written by smart people.

http://www.jooq.org/

I never cared for the library until I realized I'm spending a lot of time on the developer's blog; he is prolific and very knowledgeable about everything database and java. Was sold on it soon after.

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#138
post #135
post #132

Earlier quoted context omitted.

I wanted to ask you, what about running multiple operations in parallel? I've long been contemplating async/futures vs lightweight threads and yet to have come to a conclusion. With futures I can say, start operation 1 and operation 2 in parallel, then chain a callback to execute using both pieces of data, saving me some latency of doing the operations serially. How do you do this using quasar? Now that's a trivial e…

With lightweight threads you can spawn as many fibers as you like. Creating and starting a new fiber is basically free. You can start fibers and join them, in any dependency tree structure. Of course, you can keep using futures (what I call semi-blocking API), only futures that block the fiber rather than the thread, when you join them.

Okay so to run operations in parallel you have to go back to futures, and for more complex dependencies you would need callbacks/transforms. So this means with fibres you could use the simpler synchronous model for serial operations, but future model for parallelism, i.e. a hybrid model. My thoughts are that it might be simpler to adopt a single model rather than two. On the flip side you could argue that with fibres you don't need to use the more complicated parallelism model all the time and only when needed.

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#139
post #35

Do you really need to write a controller and all its actions for each resource with Jersey?

For static resources you can load them like this:

    public class WebAppConfig extends ResourceConfig {
      private final String[] mimeTypes;
    
      public WebAppConfig() throws IOException {
        //load static resource from htdocs dir
        Collection files = FileUtils.listFiles(new File("./htdocs"), null, true);
        ArrayList mimeTypeList = new ArrayList();
        for (File file : files) {
          final byte[] contents = FileUtils.readFileToByteArray(file);
          Resource.Builder resourceBuilder = Resource.builder();
          resourceBuilder.path(file.getAbsolutePath().split("/htdocs/")[1]);
          final ResourceMethod.Builder methodBuilder = resourceBuilder.addMethod("GET");
          String mimeType = Files.probeContentType(Paths.get(file.toURI()));
          if (!mimeTypeList.contains(mimeType)) {
            mimeTypeList.add(mimeType);
          }
          methodBuilder.produces(mimeType)
              .handledBy(new Inflector() {
                @Override
                public byte[] apply(ContainerRequestContext req) {
                  return contents;
                }
              });
          registerResources(resourceBuilder.build());
        }
         
        //load dynamic resources implementing interface Webpage
        register(MultiPartFeature.class);
        Reflections reflections = new Reflections(new ConfigurationBuilder()
            .setUrls(ClasspathHelper.forJavaClassPath())
            .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("com.example.mycompany"))));
        Set> webpageClasses = reflections.getSubTypesOf(Webpage.class);
        for (Class webpageClass : webpageClasses) {
          registerResources(Resource.builder(webpageClass).build());
        }
        mimeTypes = mimeTypeList.toArray(new String[0]);
      }
    
      public String[] mimeTypes() {
        return mimeTypes;
      }
    }
    ...

      public synchronized void start() throws Exception {
        WebAppConfig config = new WebAppConfig();
        HttpServer httpServer =
            GrizzlyHttpServerFactory.createHttpServer(URL, config, false);
        CompressionConfig compressionConfig =
            httpServer.getListener("grizzly").getCompressionConfig();
        compressionConfig.setCompressionMode(CompressionConfig.CompressionMode.ON);
        compressionConfig.setCompressionMinSize(1);
        compressionConfig.setCompressableMimeTypes(config.mimeTypes());
        httpServer.start();
        wait();
      }

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#140

I am especially fond of his view on database layers. There's JDBC, which is extremely verbose and needs scaffolding to make it usable, and then ORMS, that will quickly fall apart the moment you actually need to do anything interesting with the database. The Spring solution to this problem was always my favorite part of their stack: JDBC template removed most of the error prone boilerplate from JDBC, adds a couple of…

That is precisely why I created this little project. It generates the boiler plate code to leverage jdbcTemplate and organize the data access objects.

http://huherto.github.io/springyRecords/goals/

Also, this fellow HNer has been experimenting with Java 8 features. Pretty cool. https://github.com/benjiman/benjiql

Post reply on HN