Spring boot and Open UI5 error : JSON.parse: unexpected end of data – when setting resourceroots

Problem : After setting the tag data-sap-ui-resourceroots the UI5 loading stops with the error “JSON.parse: unexpected end of data …”

Reason : Spring boot thymeleaf view formatter changes single quotes to double quotes, thus braking the valid JSON format of the tag.

    <script src="/resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-theme="sap_belize" data-sap-ui-libs="sap.m" data-sap-ui-compatVersion="edge" data-sap-ui-preload="async" data-sap-ui-resourceroots="{"demo":"uidemo"}">
<!-- note the stupid double quotes in the json at the end of above line -->
<!-- this was originally single quotes - '{"demo":"uidemo"}' -->

Fix :  

  • Make the landing page a static HTML instead of a view template (move from templates folder to static, in Spring boot).
  • OR
  • Move to Velocity or JSP formatters

Spring boot : Testing Cassandra Repositories using Cassandra Unit

 

This short tutorial is about getting test classes running for the Cassandra repositories in a Spring boot application. The example provided uses Maven, Spring-data-cassandra and Cassandra-Unit. It also uses Lombok plugin, which is why you won’t see any getters/setters in these beans.

Step 1 : Add dependencies

Add these dependencies in your POM file –

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-cassandra</artifactId>
        </dependency>
        <dependency>
            <groupId>com.datastax.cassandra</groupId>
            <artifactId>cassandra-driver-core</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.cassandraunit</groupId>
            <artifactId>cassandra-unit-spring</artifactId>
            <version>3.1.1.0</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.cassandraunit</groupId>
                    <artifactId>cassandra-unit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.cassandraunit</groupId>
            <artifactId>cassandra-unit</artifactId>
            <classifier>shaded</classifier>
            <version>3.1.1.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.cassandraunit</groupId>
            <artifactId>cassandra-unit-spring</artifactId>
            <version>3.1.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.hectorclient</groupId>
            <artifactId>hector-core</artifactId>
            <version>2.0-0</version>
            <scope>test</scope>
        </dependency>

Step 2 : Deciding on alternate port for test Cassandra and creating a corresponding YAML file.

  1. Download this file : another-cassandra.yaml
  2. Edit the property “native_transport_port” to the port you need the test (embedded) Cassandra to listen to. The port configured in the file is 9152, which can be used unchanged.
  3. Add the file to class-path (resources folder).

Step 3 : Write a simple test to check if the embedded Cassandra starts up fine.

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.io.IOException;

import me.prettyprint.cassandra.service.CassandraHostConfigurator;
import me.prettyprint.hector.api.Cluster;
import me.prettyprint.hector.api.ddl.KeyspaceDefinition;
import me.prettyprint.hector.api.factory.HFactory;

import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;


public class EmbededCassandraTest {
    @Before
    public void before() throws TTransportException, IOException, InterruptedException, ConfigurationException {
        EmbeddedCassandraServerHelper.startEmbeddedCassandra("another-cassandra.yaml", 20000);
    }

    @Test
    public void shouldHaveAnEmbeddedCassandraStartOn9175Port() throws Exception {
        Cluster cluster = HFactory.getOrCreateCluster("TestCluster", new CassandraHostConfigurator("localhost:9175"));
        assertThat(cluster.getConnectionManager().getActivePools().size(), is(1));
        KeyspaceDefinition keyspaceDefinition = cluster.describeKeyspace("system");
        assertThat(keyspaceDefinition, notNullValue());
        assertThat(keyspaceDefinition.getReplicationFactor(), is(1));

    }
    @AfterClass
    public static void cleanCassandra() {
        EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
    }
}

Step 4: Create or Edit the application-test.properties for setting the embedded cassandra server settings for the test profile.

Add these properties to application-test.properties. Note that these properties would be picked by the config file we will add in steps further down.

cassandra.hosts=localhost
cassandra.port=9152
cassandra.keyspace=yourkeyspace

Step 5: Spring boot Java Config files

These are the main and test Cassandra config classes for this example –

Main Cassandra Config:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;


@Configuration
@EnableCassandraRepositories("package.of.your.repositories")
public class CassandraConfig extends AbstractCassandraConfiguration {

    @Value("${cassandra.hosts}")
    String cassandraHosts;
    @Value("${cassandra.port}")
    String cassandraPort;
    @Value("${cassandra.keyspace}")
    String cassandraKeySpace;

    @Override
    public String getKeyspaceName() {
        return cassandraKeySpace;
    }

    @Bean
    public CassandraClusterFactoryBean cluster() {
        CassandraClusterFactoryBean cluster =
                new CassandraClusterFactoryBean();
        cluster.setContactPoints(cassandraHosts);
        cluster.setPort(Integer.parseInt(cassandraPort));
        return cluster;
    }


    @Override
    public SchemaAction getSchemaAction() {
        return SchemaAction.CREATE_IF_NOT_EXISTS;
    }
    @Override
    public String[] getEntityBasePackages() {
        return new String[]{
                "package.of.your.domains"};
    }
}

Test Cassandra Config :

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.ActiveProfiles;


@Configuration
@ActiveProfiles("test")
@PropertySource( {"classpath:application.properties",
        "classpath:application-test.properties"})
public class CassandraTestConfig extends CassandraConfig {

}

Step 6 : Write the abstract test class

Write this abstract class which the repository test classes can inherit, and which will abstract out the Cassandra configurations :


import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
import com.mycompany.config.CassandraTestConfig;
import lombok.extern.slf4j.XSlf4j;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.springframework.context.annotation.Import;

import java.io.IOException;
import java.util.Properties;


@Import(CassandraTestConfig.class)
@XSlf4j
public abstract class AbstractRepositoryTest {

    @BeforeClass
    public static void initCassandra() {
        try {
            Properties prop = new Properties();
            prop.load(AbstractRepositoryTest.class.getClassLoader().getResourceAsStream("application-test.properties"));
            String cassandraHosts = prop.getProperty("cassandra.hosts");
            String cassandraPort = prop.getProperty("cassandra.port");

            EmbeddedCassandraServerHelper.startEmbeddedCassandra("another-cassandra.yaml", 20000);
            log.info("Connect to embedded db");
            Cluster cluster = Cluster.builder().addContactPoints(cassandraHosts).withPort(Integer.parseInt(cassandraPort)).build();
            Session session = cluster.connect();

            log.info("Initialize keyspace");
            session.execute("create keyspace  \"mykeyspace\" WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 3};");
            session.execute("use \"mykeyspace\";");
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Before
    public void initTest() {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @AfterClass
    public static void cleanCassandra() {
        EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
    }

}

Step 7 :  Domain Object/Entity

import com.datastax.driver.core.utils.UUIDs;
import lombok.Data;
import org.springframework.cassandra.core.Ordering;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;

import java.io.Serializable;
import java.util.UUID;


@Data
@Table(value = "sampleEntity")
public class SampleEntity implements Serializable {
    @PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED, ordering = Ordering.DESCENDING)
    private UUID id;
    private String text;
}

Step 8 :  Repository for ze entity


import org.springframework.data.cassandra.repository.CassandraRepository;

import java.util.List;
import java.util.UUID;

public interface SampleEntityRepository extends CassandraRepository<SampleEntity> {
    SampleEntity findById(UUID id);
}

Step 9 : The repository test, gentlemen !


import com.datastax.driver.core.utils.UUIDs;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;
import java.util.UUID;


@RunWith(SpringJUnit4ClassRunner.class)
public class SampleEntityRepoTest extends AbstractRepositoryTest {

    @Autowired
    SampleEntityRepository sampleEntityRepository;

    @Test
    public void saveOneTest() {
        UUID id = UUIDs.timeBased();
        SampleEntity sampleEntity = new SampleEntity();
        sampleEntity.setId(id);
        sampleEntity.setText("Hi");
        sampleEntity = sampleEntityRepository.save(sampleEntity);
        SampleEntity retrievedSampleEntity = sampleEntityRepository.findById(id);
        Assert.assertEquals("Hi", sampleEntity.getText());
    }
    //other tests...
}

Done.
Run the test class to confirm the setup works (or not – which case you are on your own).

How to show custom favicon in Vaadin UI ?

Add this custom Vaadin servlet to show a different favicon (other than the Vaadin default) in your UI application –


import com.vaadin.server.*;
import com.vaadin.spring.server.SpringVaadinServlet;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;

@Component("vaadinServlet")
public class CustomServlet extends SpringVaadinServlet {

    @Override
    protected void servletInitialized() throws ServletException {
        super.servletInitialized();

        getService().addSessionInitListener((SessionInitListener) event -> event.getSession().addBootstrapListener(new BootstrapListener() {

            @Override
            public void modifyBootstrapFragment(
                    BootstrapFragmentResponse response) {
                // TODO Auto-generated method stub

            }

            @Override
            public void modifyBootstrapPage(BootstrapPageResponse response) {
                response.getDocument().head().
                        getElementsByAttributeValue("rel", "shortcut icon").attr("href", "./images/favicon.png");
                response.getDocument().head()
                        .getElementsByAttributeValue("rel", "icon")
                        .attr("href", "./images/favicon.png");
            }}
        ));

    }
}

Openfire does not listen to port 5222

Problem : Openfire server does not listen to port 5222.

Symptoms :

  1. netstat -tulpn | grep LISTEN
    • – will not show ports 5222 or 5223.
  2. tail -1000 /opt/openfire/logs/stderror.log
    • Will show these entries –
      • Error starting 5222: null
        Error starting 5223: null
        Error starting 5275: null
        Error starting 5276: null
        Error starting 5262: null
        Error starting 5263: null

Reason : Unknown – but related to OpenJDK.

Fix : Run OpenFire on Oracle JDK (v8 worked, didn’t test on v9)

Extract a selected polygon from an image to a new image file in Java

A reference code to extract a selected shape (this case polygon, could be another shape like Rectangle) –


 BufferedImage in = ImageIO.read(new File(sourceFilePath));
 
Rectangle bounds = inputPolygon.getBounds(); // Polygon inputPolygon

 BufferedImage extractor =new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_ARGB);

 Graphics2D g = extractor.createGraphics();

 polygon.translate(-bounds.x, -bounds.y);

 g.setClip(polygon);

 g.drawImage(in, -bounds.x, -bounds.y, null);

 File extImageFile = new File(targetFilePath);

 ImageIO.write(extractor, "png", extImageFile);


Torch installation fails with message “Error. OpenBLAS could not be compiled”

Problem : Torch installation fails to install dependencies (“bash install-deps”) with the message “Error. OpenBLAS could not be compiled”

Reason : gfortran dependencies could not be located.

Fix : Make sure gfortran and gcc are of the same versions. On terminal –

gcc --version
gfortran --version
sudo update-alternatives --config gcc
Enter the number corresponding to the version of gfortran. (my case 5)
Run install-deps again.

Should finish to completion this time.