mapjfx 1.13.1 using OpenLayers 4.2.0

I just released mapjfx version 1.13.1 it should be found shortly at maven central, the artifact coordinates are:

  <dependency>
    <groupId>com.sothawo</groupId>
    <artifactId>mapjfx</artifactId>
    <version>1.13.1</version>
  </dependency>

The source is available at GitHub.

Now uses OpenLayers 4.2.0.

Comments and contributions welcome.

the shortest code to throw a NullPointerException

If I were to throw a NullpointerException from within my code I normally would code something like this:

if(somethingIsNull) {
  throw new NullPointerException();
}

While reading the code examples on https://github.com/reactive-streams/reactive-streams-jvm I just saw this definitely shorter possibility which I did not know up to now:

if(somethingIsNull) {
  throw null;
}

mapjfx 1.13.0 adds the possibility to exclude URLs from being cached

I just released mapjfx version 1.13.0 it should be found shortly at maven central, the artifact coordinates are:

  <dependency>
    <groupId>com.sothawo</groupId>
    <artifactId>mapjfx</artifactId>
    <version>1.13.0</version>
  </dependency>

The source is available at GitHub.

The offline cache now can be configured with a collection of Strings (Java RegExp patterns) so that URLs matching any of these will not be cached.

 

Comments and contributions welcome.

rxjava2 producer-consumer example with backpressure implementation

This post is a small example how to implement a producer and consumer using rxjava2. The producer produces a sequence of Integer objects which are consumed by the consumer. The producer only produces as much items as are requested by the reactive stream. The reader of this post should be familiar with the reactive streams concept.

project setup

I used a maven project, the only dependency needed for this example besides logging is rxjava:

<dependency>
    <groupId>io.reactivex.rxjava2</groupId>
    <artifactId>rxjava</artifactId>
    <version>2.0.8</version>
</dependency>

the producer

The producer is initialized with the integer values defining the range that is to be produced. It extends the Flowable<Integer> class and therefore must implement the subscribeActual method. In this method a new Subscription object is created which keeps track of the current value to be produced and which emits the values to the subscriber on request. By implementing the Subscription as an anonymous class it is easily possible to access the subscriber that the subscription belongs to. Care must be taken as the call to the subscribers onNext() method can result in a new recursive call to request() by the subscriber.

/**
 * class to produce Integer values using a Flowable.
 */
class TestProducer extends Flowable<Integer> {
    static final Logger logger = LoggerFactory.getLogger(TestProducer.class);
    final int from, to;

    public TestProducer(int from, int to) {
        this.from = from;
        this.to = to;
    }

    @Override
    protected void subscribeActual(Subscriber subscriber) {
        subscriber.onSubscribe(new Subscription() {

            /** the next value. */
            public int next = from;
            /** cancellation flag. */
            private volatile boolean cancelled = false;
            private volatile boolean isProducing = false;
            private AtomicLong outStandingRequests = new AtomicLong(0);

            @Override
            public void request(long n) {
                if (!cancelled) {

                    outStandingRequests.addAndGet(n);

                    // check if already fulfilling request to prevent call  between request() an subscriber .onNext()
                    if (isProducing) {
                        return;
                    }

                    // start producing
                    isProducing = true;

                    while (outStandingRequests.get() > 0) {
                        if (next > to) {
                            logger.info("producer finished");
                            subscriber.onComplete();
                            break;
                        }
                        subscriber.onNext(next++);
                        outStandingRequests.decrementAndGet();
                    }
                    isProducing = false;
                }
            }

            @Override
            public void cancel() {
                cancelled = true;
            }
        });
    }
}

the consumer

The consumer extends DefaultSubscriber<Integer>. On start, it requests one item, and after processing the next item, it requests the next one. To build up a little backpressure on the producer, there’s a little delay every 5 items.

/**
 * TestConsumer derived from DefaultSubscriber. requests one item at a time.
 */
class TestConsumer extends DefaultSubscriber<Integer> {

    private static final Logger logger = LoggerFactory.getLogger(TestConsumer.class);

    @Override
    protected void onStart() {
        request(1);
    }

    @Override
    public void onNext(Integer i) {
        logger.info("consuming {}", i);
        if (0 == (i % 5)) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException ignored) {
                // can be ignored, just used for pausing
            }
        }
        request(1);
    }

    @Override
    public void onError(Throwable throwable) {
        logger.error("error received", throwable);
    }

    @Override
    public void onComplete() {
        logger.info("consumer finished");
    }
}

 putting it together

In the main method of the test program, a producer and a consumer are created. Then the producer is set to run on the Schedulers.computation() threadpool and emit its value on the Schedulers.single() thread to make producing and consuming parallel. The consumer does a blocking subscribe to keep the main thread running until all items are processed.

public static void main(String[] args) {
    try {
        final TestProducer testProducer = new TestProducer(1, 1_000);
        final TestConsumer testConsumer = new TestConsumer();

        testProducer
                .subscribeOn(Schedulers.computation())
                .observeOn(Schedulers.single())
                .blockingSubscribe(testConsumer);

    } catch (Throwable t) {
        t.printStackTrace();
    }
}

Basically that is all that is needed for a simple reactive producer-consumer implementation.

mapjfx 1.12.2 – no default caching

I just released mapjfx version 1.12.2 it should be found shortly at maven central, the artifact coordinates are:

  <dependency>
    <groupId>com.sothawo</groupId>
    <artifactId>mapjfx</artifactId>
    <version>1.12.2</version>
  </dependency>

The source is available at GitHub.

The test program in the library and the mapjfx-demo now do not use the offline cache by default.

The caching seems to get problems the more the backing servers are using https. And Bing for example uses https calls to validate the token, which should not be cached.

Alas it is not possible only to cache the map image data, because only from the url being retrieved, there is no possibility to decide wether it’s image data or something other.

So the best seems to be not use the cache by default.

Comments and contributions welcome.

mapjfx 1.12.1 with fixes to the code for caching data

I just released mapjfx version 1.12.1 it should be found shortly at maven central, the artifact coordinates are:

  <dependency>
    <groupId>com.sothawo</groupId>
    <artifactId>mapjfx</artifactId>
    <version>1.12.1</version>
  </dependency>

The source is available at GitHub.

I implemented some improvemtnes to the code that does the caching of map images.

 

Comments and contributions welcome.

mapjfx 1.12.0 has a custom event for selecting a map area

I just released mapjfx version 1.12.0 it should be found shortly at maven central, the artifact coordinates are:

  <dependency>
    <groupId>com.sothawo</groupId>
    <artifactId>mapjfx</artifactId>
    <version>1.12.0</version>
  </dependency>

The source is available at GitHub.

The MapView now triggers a custom event when the user drags a rectangle while holding the cmd key (on Mac OSX) or the ctrl key (on Windows). This can be used to set the extent of the map to the selected extent, sample code from the mapjfx-demo app:

mapView.addEventHandler(MapViewEvent.MAP_EXTENT, event -> {
            event.consume();
            mapView.setExtent(event.getExtent());
});

 

Comments and contributions welcome.

mapjfx 1.11.0 using OpenLayers 4.0.1

I just released mapjfx version 1.11.0 it should be found shortly at maven central, the artifact coordinates are:

  <dependency>
    <groupId>com.sothawo</groupId>
    <artifactId>mapjfx</artifactId>
    <version>1.11.0</version>
  </dependency>

The source is available at GitHub.

Now uses OpenLayers 4.0.1.

Comments and contributions welcome.

mapjfx 1.10.1 has right clicked event for the map

I just released mapjfx version 1.10.1 it should be found shortly at maven central, the artifact coordinates are:

  <dependency>
    <groupId>com.sothawo</groupId>
    <artifactId>mapjfx</artifactId>
    <version>1.10.1</version>
  </dependency>

The source is available at GitHub.

Now there is a custom event for context (right) clicks in the map., not only for the markers and labels.

Comments and contributions welcome.

mapjfx 1.10.0 now supports custom WMS servers

I just released mapjfx version 1.10.0 it should be found shortly at maven central, the artifact coordinates are:

  <dependency>
    <groupId>com.sothawo</groupId>
    <artifactId>mapjfx</artifactId>
    <version>1.10.0</version>
  </dependency>

The source is available at GitHub.

As additional map type, WMS server support was added. The WMS server i s configured programmatically with a special parameter object. The demo contains two WMS servers.

Comments and contributions welcome.