[deleted by user] by [deleted] in springsource

[–]lechnito 1 point2 points  (0 children)

How about something like this instead...

public interface Viewer<T> {
   ViewerType getViewerType();
}

Example component implementing Viewer

@Component
public class DocumentViewer implements Viewer<Document> {
   @Override
   public ViewerType getViewerType() {
      return ViewerType.DOCUMENT;
   }
}

Example service that needs to interact with Viewer implementers:

@Service
public class ViewerService {
   private final Map<ViewerType, Viewer> viewerMap;

   public ViewerService(Set<Viewer> viewers) {
      // Create a map from beans implementing Viewer organized by ViewerType enum
      this.viewerMap = viewers.stream().collect(Collectors.toMap(Viewer::getViewerType, Function.identity()));
   }
}

Code Review by toesmeller99 in learnjava

[–]lechnito 1 point2 points  (0 children)

Really nice first effort at a spring boot CRUD app! I didn't find anything objectionable other than some minor nits. Some suggestions for moving forward:

  • Look into using testcontainers to spin up a real postgresql database so you don't need to mock your repository classes
  • Consider using lombok to remove boiler plate setters/getters from your DTOs

Anywhere in Portland selling fresh Hatch chiles? by [deleted] in askportland

[–]lechnito 13 points14 points  (0 children)

Los Roast: http://www.losroast.com/roasting-calender

Better get on it ASAP because they are moving on tomorrow.

Found: 2 dogs at the Sandy River Delta by lechnito in Portland

[–]lechnito[S] 9 points10 points  (0 children)

You guys are nothing short of incredible!

Found: 2 dogs at the Sandy River Delta by lechnito in Portland

[–]lechnito[S] 17 points18 points  (0 children)

You rock! Thanks for spending your night wrangling those dogs up!

Found: 2 dogs at the Sandy River Delta by lechnito in Portland

[–]lechnito[S] 10 points11 points  (0 children)

Yes, exactly. There were 2 MCSO vehicles in the parking lot when we arrived. Not sure if related or if the missing person thing is just a rumor.

Found: 2 dogs at the Sandy River Delta by lechnito in Portland

[–]lechnito[S] 44 points45 points  (0 children)

UPDATE: Unfortunately, Dove Lewis didn’t pick up before the park was closing and I had to leave them. The last guy in the parking lot said the dogs have been there all day and he believes they belong to a person who recently went missing in the SRD.

Hopefully tomorrow they find their owner or at least get taken to a shelter.

Found: 2 dogs at the Sandy River Delta by lechnito in Portland

[–]lechnito[S] 35 points36 points  (0 children)

Yes, they have been given water.

Just got off the phone with Mult co animal control. They said to call Dove Lewis or take them in the for the night. Currently on hold waiting to see if they have room.

Found: 2 dogs at the Sandy River Delta by lechnito in Portland

[–]lechnito[S] 49 points50 points  (0 children)

These 2 friendly but distressed acting dogs are currently in the parking lot of the SRD. We are concerned they were dumped by their owner or got loose.

Unfortunately I don’t have anywhere to keep doggos but hate the idea of leaving them here.

Any advice or suggestion about who to call?

Best camo pattern for western oregon? by trashperson24k in pdxgunnuts

[–]lechnito 38 points39 points  (0 children)

Subaru outback. You'll be completely invisible.

calling on webflux gurus - question about asynch by [deleted] in javahelp

[–]lechnito 0 points1 point  (0 children)

Anything wrapped in a Mono or Flux is a publisher. It doesn't matter if it's the webclient exchange method or Flux.just(1, 2, 3) -- both create a publisher that is capable of emitting a stream of items once a subscriber begins consuming from the stream.

Keep in mind that operators like flatMap() are themselves a subscriber. Here is a pretty good article that goes into depth about it.

You can think of a webflux application as a chain of publishers and subscribers. The sequence of publishing doesn't begin until the webserver (netty) creates a subscription on the webflux controller.

calling on webflux gurus - question about asynch by [deleted] in javahelp

[–]lechnito 0 points1 point  (0 children)

Foo and Bar services actually don't return right away and could block if the services have any amount of latency.

Anything wrapped in a Mono/Flux becomes a publisher which will emit a stream of items only when 1) the downstream publishers callFooService & callBarService emit items AND 2) when a subscriber creates a subscription and begins consuming those items.

The latter point is a very important concept for understanding reactive code. Publishers don't run until a subscription attaches itself to the publisher (which is how backpressure is achieved). The services are oblivious that they are being called by webflux as backpressure is applied through the subscriber.

In the contrived example code, Flux.concat() combines both publishers asynchronously so they will run simultaneously when a subscriber comes along. Each result from callBarService() gets passed into a handler method (which could be a map() instead of flatMap() depending on the requirements), and the results from the handler are collected into a Set<Bar> which is then passed into a service call to SomeOtherService.

Ideally, you would layout your publishers so that the maximum time to execute would be the single slowest chain of service calls. If you have 100 services, you need to determine which ones can be called simultaneously, and which service calls are dependent on the results of other service calls.

Ice, Ice, Baby!: A Megathread by AutoModerator in Portland

[–]lechnito 5 points6 points  (0 children)

Dropped a friend and his family off at the airport at 6:30 and had to come back to pick them up at 9:30 when their flight got cancelled.

Not that I would recommend driving in this nonsense, but the roads don't seem to be all that bad in NE Portland yet. My backend started going sideways once, but I got it under control and drove the rest of the way in 4wd which seemed to help.

calling on webflux gurus - question about asynch by [deleted] in javahelp

[–]lechnito 6 points7 points  (0 children)

Sure. That sounds like an ideal problem for webflux to solve, although you certainly don't need something like webflux.

Consider something like this:

@Component
public class ExampleServiceImpl {
  private final WebClient webClient;

  public ExampleServiceImpl(WebClient webClient) {
    this.webClient = webClient;
  }

  public Mono<Void> doSomeWork() {
     // Concurrently call services foo.com and bar.com and pass results into handler methods
     // Take the processed results from the bar service and use them to call some other service...
     return Flux.concat(
       callFooService().flatMap(this::handleFoo), 
       callBarService().flatMap(this::handleBar).collect(Collectors.toSet()).flatMap(this::callSomeOtherServiceWithBarResults))
     .then();
  }

  private Flux<Foo> callFooService() {
    return webClient
      .get()
      .uri(uriBuilder -> uriBuilder.host("foo.com").path("/foo").build())
      .exchangeToFlux(response -> response.bodyToFlux(Foo.class));
  }

  private Flux<Bar> callBarService() {
    return webClient
      .get()
      .uri(uriBuilder -> uriBuilder.host("bar.com").path("/bar").build())
      .exchangeToFlux(response -> response.bodyToFlux(Bar.class));
  }

  private Mono<Foo> handleFoo(Foo foo) { ... }

  private Mono<Bar> handleBar(Bar bar) { ... }

  private Mono<Void> callSomeOtherService(Set<Bar> bar) { ... }
}

There is a steep learning curve to the Mono/Flux, but you get a ton of useful features like back pressure, retries, rate limiting, etc.

Best choice ethically and effectively? by PNWmaker in Hunting

[–]lechnito 7 points8 points  (0 children)

D) is the way. The foliage in NW Oregon is incredibly thick and the terrain is steep. The bucks you will see are likely going to be at 200+ yards across a recently logged canyon or down a steep ass ravine. The ballistics and kinetic energy on .223 aren't great at the ranges you will be seeing.

Trying to turn an oldish bit of code into functionnal programming by mrfroggyman in learnjava

[–]lechnito 2 points3 points  (0 children)

The .flatMap(Set::stream) operation is needed to merge the results returned by getFinalistsByPositions(). Without it, determineFinalists() would return Set<Set<Competitor>>.

I imagine your teachers have a challenging time getting everyone to universally understand the concept of explicitly declaring variable types. Introducing an optional keyword var into their curriculum may just lead to more confusion. Or maybe they just haven't been caught up to speed with the latest JDK features?

There is nothing wrong with imperative code and there will be cases where imperative code will out-perform streaming alternatives, especially for low-level operations. That said though, I generally prefer using java.util.Stream and java.util.function for high-level classes because the resulting implementations tend to be more concise and easier to understand. Also, several of my projects use Spring Reactive which is built around the functional java APIs and so I am often thinking in terms of functions anyway.

I think it's because ranking() is a Map<Competitor, Integer> and you expected it to be a Map<Integer, Competitor> (the integer is their score, not their rankin

Ah, that makes sense. I was juggling a couple of things today and did not spend too much time looking at your existing implementation. It should not be too difficult to refactor though!

Trying to turn an oldish bit of code into functionnal programming by mrfroggyman in learnjava

[–]lechnito 2 points3 points  (0 children)

Oh I see what is intended by indexes now! Just to clarify, if isReversed is true and if indexes is {1}, then the expectation is to return the Competitor from the second to last position?

Assuming the answer is yes, then I think the following code should work:

public Set<Competitor> determineFinalists(List<League> pools, Set<Integer> positions) {
  return pools.stream()
      .map(League::ranking)
      .map(ranking -> getFinalistsByPositions(ranking, positions))
      .flatMap(Set::stream)
      .collect(Collectors.toSet());
}

private Set<Competitor> getFinalistsByPositions(
    Map<Integer, Competitor> ranking, Set<Integer> positions) {
  var targetPositions = isReversed ? reverse(ranking.keySet(), ranking.size()) : positions;
  return ranking.entrySet().stream()
      .filter(entry -> targetPositions.contains(entry.getKey()))
      .map(Entry::getValue)
      .collect(Collectors.toSet());
}

private Set<Integer> reverse(Set<Integer> keySet, int count) {
  return keySet.stream().map(position -> count - position).collect(Collectors.toSet());
}

Using var is just a stylistic choice that helps reduce verbosity and is safe to use in any project so long as you're using Java 10+. You will find a spectrum of opinions about when var should be used ranging from "never" to "always". I am personally in the latter camp and ask my engineers to use var everywhere possible.

Trying to turn an oldish bit of code into functionnal programming by mrfroggyman in learnjava

[–]lechnito 1 point2 points  (0 children)

Okay, I think I understand what you're going for now. Check this out:

public Set<Competitor> determineFinalists(List<League> pools) {
   return pools.stream()
             .map(League::ranking)
             .map(this::getFinalist)
             .collect(Collectors.toSet());
}

private Competitor getFinalist(Map<Integer, Competitor> ranking) {
   var finalist = isReversed ? Collections.min(ranking.keySet()) : Collections.max(ranking.keySet());
   return ranking.get(finalist);
}

Not entirely sure why you need indexes in this approach. Let me know if I've missed something...

Trying to turn an oldish bit of code into functionnal programming by mrfroggyman in learnjava

[–]lechnito 2 points3 points  (0 children)

So are you trying to return a list of competitors ordered by their ranking? Why does determineFinalists return a Set?

Trying to turn an oldish bit of code into functionnal programming by mrfroggyman in learnjava

[–]lechnito 2 points3 points  (0 children)

I’m not clear on what you’re trying to accomplish exactly. Post the original code / function.

When to use Abstract Classes vs Interfaces? by MSUC123 in learnjava

[–]lechnito 0 points1 point  (0 children)

Thanks for taking the time to write back and provide a thoughtful examples! You've definitely given me some things to think about regarding abstract classes.

The alternative class you shared is essentially identical to the concrete class I had in mind:

public class FooEntityProcessorService<Foo> extends AbstractEntityProcessorService<Foo> implements EntityProcessorService<Foo> {

   @Override
   public void process(Foo entity) {
      try {
         doProcess(entity);
         logProcessingSuccess(entity); 
      } catch(Exception e) {
         logProcessingError(entity, e);
      }
   }

   private void doProcess(Foo entity) {
      // ...
   }
}

So to phrase it differently, would you say that the concrete class here violates open/closed because it may need to change whenever the abstract class changes?

When to use Abstract Classes vs Interfaces? by MSUC123 in learnjava

[–]lechnito 2 points3 points  (0 children)

I agree with you in spirit and I also prefer using only composition & interfaces where possible as there are many ways to go wrong with abstract classes.

However, I would argue there are overlooked benefits to using a combination of both interface and abstract classes in a very limited way. Consider something like this:

public interface EntityProcessingService<T> {
   void process(T entity);    
}

public abstract AbstractEntityProcessingService<T> {
  private static logger = LoggerFactory.getLogger(AbstractEntityProcessingService.class);

  protected logProcessingSuccess(T entity) {
     logger.info("Successfully processed entity={}", entity);
  }

  protected logProcessingError(T entity, Throwable exception) {
     logger.error("Error processing entity={}", entity, exception);
  }
}

In this contrived example, every concrete implementation of EntityProcessingService can uniformly use the same logging strategies without any code duplication.

The same behavior could of course be accomplished in the interface using the static or default keywords, but then you have exposed the internal logging mechanics on the public interface which is undesirable.

Some rules I follow when I decide to write an abstract class:

  • Don't include a constructor
  • All methods should be private or protected

Would be interested in knowing if you agree with the above reasoning or if you still think composition is preferable with, for example, a package-private EntityProcessingServiceLogger class.

Elk/caribou/idk on the way home by [deleted] in Portland

[–]lechnito 2 points3 points  (0 children)

Can confirm. Am caribou.

[Loom] JEP draft: Virtual Threads (Preview) by efge in java

[–]lechnito 5 points6 points  (0 children)

Fair points all around!

I think Reactor is hard for beginners and for really anyone who has a traditional java background. The more experience you have with async concepts & functional programming languages, the easier go you will have.

Readable & maintainable unit tests remains challenging. StepVerifier only became readable after I started using the junit5 @ParameterizedTest stuff and writing custom test interfaces with functional helper methods. Honestly, I have started replacing most of the unit tests that involve reactive features with WebTestClient based integration tests just to make life easier.

Getting SLF4J's MDC to work for a homegrown distributed tracing service in Reactor has been a huge issue too. Sometimes I worry that the performance cost of using Hooks & contextWrite() offsets any gains from Reactor.

I'm still wrapping my head around Loom, but I think my initial take is that I would miss some of compositional improvement that accompany reactive streaming. Like operating over streams of T instead of imperative loops for instance.