java – detached entity passed to persist

We use jhipster as a template for one of our applications.
We have a related entity of User using a OneToOne relationship with extra information as suggested here.

The following code tries to find the user, which already must exist, and then find the related ‘extra’ information, a keyfile in this particular case, -if found- it should update it and if not it should create it and store it in the database.

@PostMapping("/key/{login:" + Constants.LOGIN_REGEX + "}")
    @Timed
    public ResponseEntity<UserKeyFile> updateKeyFile(@PathVariable String login, @RequestPart("file")MultipartFile file) {
        log.debug("peticion REST para actualizar el archivo key del usuario : {}", login);
        File fileSaved = saveToFile(file, login);

        return ResponseUtil.wrapOrNotFound(
            this.userRepository.findOneByLogin(login).flatMap(
                user -> Optional.of(
                    this.userKeyFileRepository.findById(user.getId()).map(userKeyFile -> {
                        userKeyFile.setLastModifiedDate(Instant.now());
                        return userKeyFile;
                    }).orElseGet(() -> {
                        UserKeyFile userKeyFile = new UserKeyFile();
                        userKeyFile.setUser(user);
                        userKeyFile.setRuta(fileSaved.getAbsolutePath());
                        return this.userKeyFileRepository.save(userKeyFile);
                    })
                )
            )
        );
    }

at a first attempt it threw the following error

2018-12-06 09:10:15.825 ERROR 14686 — [ XNIO-2 task-3] m.g.t.aop.logging.LoggingAspect : Exception in com.contoso.web.rest.UserKeyFileResource.updateKeyFile() with cause = ‘org.hibernate.PersistentObjectException: detached entity passed to persist: com.contoso.domain.User’ and exception = ‘detached entity passed to persist: com.contoso.domain.User; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.contoso.domain.User

as it happens, we were using two different repositories and hence the error. We just need to add the org.springframework.transaction.annotation.Transactional annotation

@Transactional
public ResponseEntity updateKeyFile(@PathVariable String login, @RequestPart(“file”)MultipartFile file) {

and now we can persist our related Entity. great!

Anuncios

glassfish – add certificate to trust store

We changed our SMTP server recently, which is used by apps to send notification emails. The problem was that the certificate it was using was issued by itself, hence when adding it to a mail client, i.e. thunderbird, it asks you to confirm the exception before it could send any mail (it requires STARTTLS).

So, in order for our apps running on a Glasfish 4.1 Server to send emails, we need to add the certificate to the trust store.

When attempting to send an email with the following code

public void sendMail(String to, String subject, String body) {
        try {
            // sets SMTP server properties
            Properties properties = new Properties();
            properties.put("mail.smtp.host", SMTP_HOST);
            properties.put("mail.smtp.port", SMTP_PORT);
            properties.put("mail.smtp.auth", "true");
            properties.put("mail.smtp.starttls.enable", "true");
            Authenticator auth = new Authenticator() {
                public PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(SMTP_USER, SMTP_PASSWORD);
                }
            };
            Session session = Session.getInstance(properties, auth);
            MimeMessage msg = new MimeMessage(session);

            msg.setFrom(new InternetAddress(SMTP_USER));
            InternetAddress[] toAddresses = {new InternetAddress(to)};
            msg.setRecipients(Message.RecipientType.TO, toAddresses);
            msg.setSubject(subject);
            msg.setSentDate(new Date());
            msg.setText(body, "utf-8", "html");

            Transport.send(msg);
        } catch (MessagingException e) {
            String error = String.format("Ocurrió un problema al enviar un CORREO a: %s", to);
            log.error(error, e);
        } catch (Exception e) {
            String error = String.format("Ocurrió un problema al enviar un CORREO a: %s", to);
            log.error(error, e);
        }
    }

The error logged on Glassfish was

Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

First get the certificate of the SMTP server. We got it through the web client accessing with Chrome and clicking on the ‘Not Secure’ label, then Certificate | Details | Export… /tmp/smtp.cer

Then we need to import it with the keytool.

To get the path where the trusted certs are stored I ran the command

ps aux | grep glass

and identified the line

-Djavax.net.ssl.trustStore={glassfish}/domains/domain1/config/cacerts.jks

Now it’s time to import the certificate. First do a backup.

cp {glassfish}/domains/domain1/config/cacerts.jks {glassfish}/domains/domain1/config/cacerts.jks.bkp

Then import the certificate

keytool -import -trustcacerts -alias smtp -file /tmp/smtp.cer -keystore {glassfish}/domains/domain1/config/cacerts.jks

done! now you can send emails through this SMTP server.

postgres – btree level 1 not found in index

We have a jira instance which uses the postgres database to store its information. The server had roughly 50 Gb of disk, so it ran out of space before we noticed. We extended the partition to 100 Gb but apparently it was too late.
Jira started complaining about it with an 500 internal server error (Estado HTTP 500 – Could not determine database type. (Conexión rechazada. Verifique que el nombre del Host y el puerto sean correctos y que postmaster este aceptando conexiones TCP/IP.)). Viewing the logs we found Caused by: java.net.ConnectException: Connection refused

We checked our database and database settings for external connections and couldn’t connect.

Then we tried to start the postgres service

sudo service postgresql start

2018-12-04 09:01:59.268 CST [21281] LOG:  database system was interrupted while in recovery at 2018-12-04 08:59:20 CST
2018-12-04 09:01:59.268 CST [21281] HINT:  This probably means that some data is corrupted and you will have to use the last backup for recovery.
2018-12-04 09:01:59.631 CST [21281] LOG:  database system was not properly shut down; automatic recovery in progress
2018-12-04 09:01:59.636 CST [21281] LOG:  redo starts at 7/CC020C68
2018-12-04 09:01:59.639 CST [21281] LOG:  record with zero length at 7/CC07E998
2018-12-04 09:01:59.639 CST [21281] LOG:  redo done at 7/CC07E968
2018-12-04 09:01:59.639 CST [21281] LOG:  last completed transaction was at log time 2018-12-03 10:29:49.99078-06
2018-12-04 09:01:59.641 CST [21281] FATAL:  btree level 1 not found in index "19881"

VITALLY IMPORTANT FIRST RESPONSE

I did a backup of the postgres data files

ssh admin@jira.server
sudo tar cvf postgres.bkp.tar /var/lib/postgresql/

Copied it to my local machine

rsync -av admin@jira.server:postgres.bkp.tar .

then installed the same version (series) that is on the server into my local machine.
Since I have ubuntu 18.04 I had to add the postgres repository to install postgres version 9.3.

echo “deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main” | sudo tee /etc/apt/sources.list.d/pgdg.list
wget –quiet -O – https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add –
sudo apt update
sudo apt install postgresql-9.3 postgresql-contrib-9.3

Then I tried to run postgres locally with the backup data

cd /tmp
tar xvf postgres.bkp.tar
sudo su postgres
/usr/lib/postgresql/9.3/bin/postgres -D /tmp/var/lib/postgresql/9.3/main/

it complained about not finding the configuration file so I just copied it from the default dirs

cp /etc/postgresql/10/main/postgresql.conf /tmp/var/lib/postgresql/9.3/main/
cp -R /etc/postgresql/10/main/conf.d/ /tmp/postgres/var/lib/postgresql/9.3/main/

edit the postgresql.conf file and change the data dir appropiately

data_directory = ‘/tmp/var/lib/postgresql/9.3/main’

then I tried again (but this time in single mode) and it reproduced exactly the same error as on server. Great!

postgres@elite-tsj:/tmp$ /usr/lib/postgresql/9.3/bin/postgres --single -P -d 1 -D /tmp/var/lib/postgresql/9.3/main/
2018-12-04 09:01:59.268 CST [21281] LOG:  database system was interrupted while in recovery at 2018-12-04 08:59:20 CST
2018-12-04 09:01:59.268 CST [21281] HINT:  This probably means that some data is corrupted and you will have to use the last backup for recovery.
2018-12-04 09:01:59.631 CST [21281] DEBUG:  checkpoint record is at 7/CC025C50
2018-12-04 09:01:59.631 CST [21281] DEBUG:  redo record is at 7/CC020C68; shutdown FALSE
2018-12-04 09:01:59.631 CST [21281] DEBUG:  next transaction ID: 0/9547804; next OID: 227497
2018-12-04 09:01:59.631 CST [21281] DEBUG:  next MultiXactId: 3; next MultiXactOffset: 5
2018-12-04 09:01:59.631 CST [21281] DEBUG:  oldest unfrozen transaction ID: 676, in database 1
2018-12-04 09:01:59.631 CST [21281] DEBUG:  oldest MultiXactId: 1, in database 1
2018-12-04 09:01:59.631 CST [21281] DEBUG:  transaction ID wrap limit is 2147484323, limited by database with OID 1
2018-12-04 09:01:59.631 CST [21281] DEBUG:  MultiXactId wrap limit is 2147483648, limited by database with OID 1
2018-12-04 09:01:59.631 CST [21281] LOG:  database system was not properly shut down; automatic recovery in progress
2018-12-04 09:01:59.634 CST [21281] DEBUG:  resetting unlogged relations: cleanup 1 init 0
2018-12-04 09:01:59.636 CST [21281] LOG:  redo starts at 7/CC020C68
2018-12-04 09:01:59.639 CST [21281] LOG:  record with zero length at 7/CC07E998
2018-12-04 09:01:59.639 CST [21281] LOG:  redo done at 7/CC07E968
2018-12-04 09:01:59.639 CST [21281] LOG:  last completed transaction was at log time 2018-12-03 10:29:49.99078-06
2018-12-04 09:01:59.639 CST [21281] DEBUG:  resetting unlogged relations: cleanup 0 init 1
2018-12-04 09:01:59.641 CST [21281] FATAL:  btree level 1 not found in index "19881"

since this data is a copy i just executed pg_resetxlog as shown here.
Be aware that use of the pg_resetxlog utility should be done as an absolute last resort, and there are still some things you should try first..

/usr/lib/postgresql/9.3/bin/pg_resetxlog /tmp/var/lib/postgresql/9.3/main/

it complained I had to force it, there you go

/usr/lib/postgresql/9.3/bin/pg_resetxlog -f /tmp/var/lib/postgresql/9.3/main/

done! Now let’s see if it’s working again

sudo su postgres
/usr/lib/postgresql/9.3/bin/postgres -D /tmp/var/lib/postgresql/9.3/main/

boom! it’s working.

Now it’s time to do a backup with sql dump (pg_dump) or better yet a full sql dump (pg_dumpall).

In another terminal (or tab)

sudo su postgres
pg_dumpall -p 5433 > /tmp/postgres-full.dmp

in my case I had to specify the port (-p 5433).

Now that I have a full backup I can try the same on production.

/usr/lib/postgresql/9.3/bin/pg_resetxlog -f /var/lib/postgresql/9.3/main/
sudo service postgresql start

thank the gods! (to recall the option pointed here)

enable ssh session using keys instead of password in dokku

ssh

We have a Dokku server installation. You can run remote commands to ease up a little bit the administration tasks.
So, to avoid the need to logon the server and run some dokku commands I needed to configure ssh keys.
First, let’s create our keys -if you haven’t yet-

ssh-keygen -t rsa

let’s copy our public key to the clipboard.

cat ~/.ssh/id_rsa.pub | xclip -selection clipboard

you can add the second command to an alias in the file ~/.bash_aliases if you wish

alias cb=’xclip -selection clipboard’

so the previous command would be

cat ~/.ssh/id_rsa.pub | cb

then we can paste our public key to the authorized clients on the server

ssh joe@dokku.me
sudo su
cd /home/dokku/.ssh
cat >> authorized_keys
press CTRL-SHIFT-V
press CTRL-C

you must prepend your public key (your key starts with the type, ssh-rsa in this case) in the authorized_keys file with the following configuration (this should have been done when installing dokku)

command=”FINGERPRINT=SHA256:qriqw51R00ha3WHe5Zo987APhwxolya3Sv5Dvwm/fqE NAME=\”admin1\” `cat /home/dokku/.sshcommand` $SSH_ORIGINAL_COMMAND”,no-agent-forwarding,no-user-rc,no-X11-forwarding,no-port-forwarding ssh-rsa AAAAB3Nza…

done!

now you can exit the server and run a remote command from your machine

ssh -t dokku@dokku.me apps:list

ubuntu – from 16.04 to 18.04

ubuntu bionic beaver logo

I used Ubuntu 16.04 for as long as I could. It turns out that Dropbox sent me a notification about dropping support for file systems different than ext4.

your Dropbox folder will stop syncing because it’s on a file system or partition that no longer meets the requirements

I thougth I was using ext4 but, since I had enabled encryption on my home folder, in reality I had ecryptfs. So I needed to use another partition if I’d like to continue using Dropbox.
I thought it wouldn’t be so hard to resize my primary partition -since I used LVM- and create another partition with ext4. Well I tried system-config-lvm and kvpm but they both required to boot from a liveusb or livecd distribution since the partition I wanted to resize was my root partition.

So I decided it would be easier, and perhaps better, for me to just upgrade to ubuntu 18.04 LTS.

I wasn’t wrong, the new version feels smoother, faster and a little bit cleaner.

The only hiccups I had were

  • no fullscreen apps (hide menu bar when maximized)
    Although you can install this gnome extension to enable this behavior.
  • HUD is gone
    I used it with gimp a lot -crop, resize, any menu command available just pressing ALT-. Well, there’s also a gnome extension for this.
  • hot corners (to change between applications pointing the mouse to a corner or CMD+W)
    You can use a gnome extension called custom corner as explained in this article.
  • adding custom launchers to dock
  • it doesn’t have a default backup manager (you can install deja-dup as it was the default before)
    > sudo apt install deja-dup
  • i needed support for exfat (it’s where I placed my last backup)
    > sudo apt install exfat-fuse exfat-utils

well, so far I’m very happy with the upgrade.

macOS – from Chrome to Safari

I’ve always wanted to switch from Chrome to Safari. It feels light and blazing fast, and of course its better integrated with apple ecosystem. But every time I tried, something didn’t completely convinced me.

Since I recently have upgraded to Mojave I thought I could give it another try. So let me talk to you about my experience.

Summary

  • password management (well you just have to login again on each service and allow safari to remember them)
  • window closes even when I have tabs pinned. (solution)
  • custom search engines (solution)

Details

window closes even when I have tabs pinned.
It feels indeed faster and smoother. The first gripes about it came when I closed a tab and it closed the whole window. It is because I’m very used to have two or three tabs pinned, and whenever I close the last tab different from the pinned ones, it closed the window. I found it is the expected behavior and how you could change it.

custom search engines
One of the most useful features I use all the time in Chrome are custom search engines. I like to just prepend my searches with one or two letters and then the search term, and have the results from whatever website (search engine) I have configured. In example, I have the following search engines configured

  • y youtube search
  • tr google translate search
  • w wikipedia search
  • d developers internal jira instance
  • etcetera…

these are very powerful and you can have them in safari too by installing the omnisearch plugin.

bootstrap space between labels in angularjs

I wanted to use labels from bootstrap 3.3 to denote tags in an element. I had an ng-repeat directive to add a label for each tag, but there was no spacing between labels.

<a ui-sref="tag.details({tag: tag})" ng-repeat="tag in post.tags"><span class="label label-default">{{tag}}</span></a>

I found that if you don’t have spaces (could be a new line) between labels or -the opposite- you have trailing spaces inside the label element, it won’t add spacing between them.

You can test it in this jsbin

Since I don’t know how to add a new line between each ng-repeat element I had to use the style attribute to add a margin between them. Besides I was using a link on each tag to transition state to the details, so I needed it anyway to style up a little bit.

<a ui-sref="tag.details({tag: tag})" ng-repeat="tag in post.tags" style="color: white;"><span class="label label-default" style="margin-left: 5px;">{{tag}}</span></a>

sources:
https://stackoverflow.com/questions/24380129/no-spacing-between-bootstrap-labels
https://forum.pagelines.com/topic/23014-how-to-make-bootstrap-labels-and-badges-become-a-link-like-button/