пʼятниця, 9 серпня 2019 р.

GIT remove commit

Small hints for myself regarding GIT.
Imagine we added 1.txt to some project and committed this file:
git add 1.txt
git commit -m 'test 1'
Then we added another file 2.txt and also committed:
git add 2.txt
git commit -m 'test 2'

After manipulations above we have the following situation:
$ git log --graph
* commit 53ec09a2cee2444877233ceca32c15779bb1d02d (HEAD -> master)
| Author: Yurii Petrovskyi
| Date:   Fri Aug 9 10:35:32 2019 +0300
|
|     test 2
|
* commit afb41e2d1fbab67a8cfaf316d41f81b73138b730
| Author: Yurii Petrovskyi
| Date:   Fri Aug 9 10:35:07 2019 +0300
|
|     test 1
|
* commit 0796e3cd0b010b3e84f565fd777811bfc3b225c4 (origin/master)

Then we need to undo the last commit (where we added 2.txt). In this case, it depends on do we want to save 2.txt file or we want to delete it. If we want to save the file and reset the last commit we need to use the next command:
git reset --soft HEAD~1
if we do not need this file at all:
git reset --hard HEAD~1

There is another scenario. We don`t want to push 1.txt from the first commit, so we should remove the file from repository's history:

git rm --cached 1.txt
git commit --amend -CHEAD

After commands above our "test 2" commit will contain removed 1.txt file and if we push it to the remote only 2.txt will be sent.

Also if we want to revert the whole specific commit we can use:
git revert commit_id

For example, I reverted "test 1" commit and this is a result:
git revert afb41e2d1fbab67a8cfaf316d41f81b73138b730
git log
commit 3ff659b964ca741a8c71dfa9ba45bcc74b66aa90 (HEAD -> master)
Author: Yurii Petrovskyi
Date:   Fri Aug 9 12:45:32 2019 +0300

    Revert "test 1"

    This reverts commit afb41e2d1fbab67a8cfaf316d41f81b73138b730.

commit 2d006836dda2d5558b4e1d2701b291c5187abfd1
Author: Yurii Petrovskyi
Date:   Fri Aug 9 12:43:44 2019 +0300

    test 2

commit afb41e2d1fbab67a8cfaf316d41f81b73138b730
Author: Yurii Petrovskyi
Date:   Fri Aug 9 10:35:07 2019 +0300

    test 1

commit 0796e3cd0b010b3e84f565fd777811bfc3b225c4 (origin/master)

If you pushed some changes and it was a mistake, in that case I used the following commands:
git reset --soft HEAD~1
git push origin -f

вівторок, 6 серпня 2019 р.

j_spring_security_check and Spring Security 4 and 405

Long story short, I migrated from Spring Security 3 to version 4.0.3.RELEASE. When I changed the version in pom file I faced with 405 error. In my login.jsp I had something like that:
*(I changed the character "<" to "!" to display the code)

!form style="margin-bottom: 0px;" action="../../j_spring_security_check" method="post">
Username:!input type="text" name="j_username" />!br/>
Password:!input type="password" name="j_password" />!br/>

Digging through Stackoverflow and other articles I found this useful link (note for the future: try to search in official documentation first :-) ):
https://docs.spring.io/spring-security/site/migrate/current/3-to-4/html5/migrate-3-to-4-xml.html#m3to4-xmlnamespace-form-login

So now I have login.jsp with the following text:

!form style="margin-bottom: 0px;" action="!c:url value='/login' />" method="POST">
Username:!input type="text" name="username" />!br/>
Password:!input type="password" name="password" />!br/>
!input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> !br/>
!input type="submit" value="Login" />

Update: For now I do not need CSRF filter in my project, so I removed one line from the code above (crossed out text) and added the following string in my spring-security.xml:
<security:csrf disabled="true" /> 

середа, 31 липня 2019 р.

NoClassDefFoundError and tools.jar

On my current project, I faced up with some bug which made me crazy:
java.lang.NoClassDefFoundError: com/sun/tools/attach/AttachNotSupportedException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethods(Class.java:1975)
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:609)
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:521)

I used IDEA, Maven and Tomcat 9. Using IDEA Ultimate I created a configuration which should run my MVC project. In POM I had:
<dependency>
   <groupId>com.sun</groupId>
   <artifactId>tools</artifactId>
   <version>1.0.0</version>
   <scope>system</scope>
   <systemPath>${project.basedir}/lib/tools.jar</systemPath>
</dependency>
And everytime I saw the exception.
The Internet did not help and I was merely suffering. However, my teammate had already faced up with this kind of issue. So he advised me to put tools.jar into:
C:\Program Files\Apache Software Foundation\Tomcat 9.0\lib

And at last, it has worked.    

середа, 17 квітня 2019 р.

Unpivot the table

Recently I had an interview and interviewer asked me how I can to rotate the following table:
To rotate means to get the following result (example for shop_id = 1):
I suggested using unpivot and e.g. in Oracle it could be smth like that:
WITH calendar as (
SELECT 1 as shop_id, 0 as mon, 0 as tue, 1 as wed, 1 as thur, 1 as fri, 0 as sat, 0 as sun FROM dual
UNION ALL
SELECT 2 as shop_id, 1 as mon, 1 as tue, 1 as wed, 1 as thur, 0 as fri, 0 as sat, 0 as sun FROM dual
)
SELECT shop_id, dayOfWeek, isWorkDay
FROM calendar
UNPIVOT (
isWorkDay
FOR dayOfWeek IN (mon, tue, wed, thur, fri, sat, sun)
)
WHERE shop_id = 1
view raw Unpivot1.sql hosted with ❤ by GitHub

But I was interrupted and the additional requirement was what would I do if the use of unpivot is prohibited? I proposed to rewrite the sql-query via UNION ALL:
WITH calendar as (
SELECT 1 as shop_id, 0 as mon, 0 as tue, 1 as wed, 1 as thur, 1 as fri, 0 as sat, 0 as sun FROM dual
UNION ALL
SELECT 2 as shop_id, 1 as mon, 1 as tue, 1 as wed, 1 as thur, 0 as fri, 0 as sat, 0 as sun FROM dual
)
SELECT * FROM (
SELECT shop_id, 'MON' as dayOfWeek, mon as isWorkDay
FROM calendar
UNION ALL
SELECT shop_id, 'TUE' as dayOfWeek, tue as isWorkDay
FROM calendar
UNION ALL
SELECT shop_id, 'WED' as dayOfWeek, wed as isWorkDay
FROM calendar
UNION ALL
SELECT shop_id, 'THUR' as dayOfWeek, thur as isWorkDay
FROM calendar
UNION ALL
SELECT shop_id, 'FRI' as dayOfWeek, fri as isWorkDay
FROM calendar
UNION ALL
SELECT shop_id, 'SAT' as dayOfWeek, sat as isWorkDay
FROM calendar
UNION ALL
SELECT shop_id, 'SUN' as dayOfWeek, sun as isWorkDay
FROM calendar
)
WHERE shop_id = 1
view raw unpivot2.sql hosted with ❤ by GitHub

However, my opponent asked me to figure out one more method via a recursive query. And here it is:
WITH calendar as (
SELECT 1 as shop_id, 0 as mon, 0 as tue, 1 as wed, 1 as thur, 1 as fri, 0 as sat, 0 as sun FROM dual
UNION ALL
SELECT 2 as shop_id, 1 as mon, 1 as tue, 1 as wed, 1 as thur, 0 as fri, 0 as sat, 0 as sun FROM dual
)
, seq as (SELECT level as lvl FROM dual CONNECT BY level <= 7)
SELECT shop_id,
case when lvl = 1 then 'mon'
when lvl = 2 then 'tue'
when lvl = 3 then 'wed'
when lvl = 4 then 'thur'
when lvl = 5 then 'fri'
when lvl = 6 then 'sat'
when lvl = 7 then 'sun'
end as dayOfWeek,
case when lvl = 1 then mon
when lvl = 2 then tue
when lvl = 3 then wed
when lvl = 4 then thur
when lvl = 5 then fri
when lvl = 6 then sat
when lvl = 7 then sun
end as isWorkDay
FROM calendar, seq
WHERE shop_id = 1
ORDER BY shop_id, lvl
view raw Unpivot3.sql hosted with ❤ by GitHub

And in general using queries above you can get the following result:

середа, 13 березня 2019 р.

The frequency of unique elements in the list

Just a small reminder for myself. You have a class:
public class Entity {
    private String name;
    private int count;

    public Entity(String name, int count) {
        this.name = name;
        this.count = count;
    }

    @Override
    public String toString() {
        return "Entity{" +
                "name='" + name + '\'' +
                ", count=" + count +
                '}';
    }
}

Then you create a test where you want to find out the frequency of every unique element (which is an instance of the class above) in the list. How can you do this? I am thinking to put all elements to HashSet to get distinct elements and then move through Set and call Collections.frequency. So the test could be like that:
import org.junit.Assert;
import org.junit.Test;
import java.util.*;

public class EntityTest {

    @Test
    public void testListToSet(){
        Entity entity1 = new Entity("Entity1", 1);
        Entity entity2 = new Entity("Entity2", 2);
        Entity entity3 = new Entity("Entity1", 1);
        Entity entity4 = new Entity("Entity2", 1);

        List entityList = new ArrayList<>(Arrays.asList(entity1, entity2, entity3, entity4));
        System.out.println("ArrayList: " + entityList);
        Assert.assertEquals(4, entityList.size());

        Set entityHashSet = new HashSet<>(entityList);
        System.out.println("HashSet: " + entityHashSet);
        Assert.assertEquals(3, entityHashSet.size());

        System.out.println("Frequency:");
        for (Entity entity : entityHashSet) {
            int frequency = Collections.frequency(entityList, entity);
            System.out.println(entity + " => " + frequency);
        }
    }

}

However, it will not work. Because you should override the equals and the hashCode methods. IDEA did it instead of me:
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Entity entity = (Entity) o;
    return count == entity.count &&
            Objects.equals(name, entity.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, count);
}

And after that the output will be next:
ArrayList: [Entity{name='Entity1', count=1}, Entity{name='Entity2', count=2}, Entity{name='Entity1', count=1}, Entity{name='Entity2', count=1}]
HashSet: [Entity{name='Entity1', count=1}, Entity{name='Entity2', count=2}, Entity{name='Entity2', count=1}]
Frequency:
Entity{name='Entity1', count=1} => 2
Entity{name='Entity2', count=2} => 1
Entity{name='Entity2', count=1} => 1

If we need to store our list to TreeSet we should implement Comparable interface and override compareTo method. My approach:
public class Entity implements Comparable {
    private String name;
    private int count;

    public Entity(String name, int count) {
        this.name = name;
        this.count = count;
    }

    @Override
    public String toString() {
        return "Entity{" +
                "name='" + name + '\'' +
                ", count=" + count +
                '}';
    }

    @Override
    public int compareTo(Entity o) {
        return Integer.compare(o.count, this.count);
    }
} 

And the test:
@Test 
public void testListToSet(){
    Entity entity1 = new Entity("Entity1", 1);
    Entity entity2 = new Entity("Entity2", 2);
    Entity entity3 = new Entity("Entity1", 1);
    Entity entity4 = new Entity("Entity2", 1);

    List entityList = new ArrayList<>(Arrays.asList(entity1, entity2, entity3, entity4));
    System.out.println("ArrayList: " + entityList);
    Assert.assertEquals(4, entityList.size());

    Set entityTreeSet = new TreeSet<>(entityList);
    System.out.println("TreeSet: " + entityTreeSet);
    Assert.assertEquals(2, entityTreeSet.size());
}

Output:
ArrayList: [Entity{name='Entity1', count=1}, Entity{name='Entity2', count=2}, Entity{name='Entity1', count=1}, Entity{name='Entity2', count=1}]
TreeSet: [Entity{name='Entity2', count=2}, Entity{name='Entity1', count=1}]

System environment variable in Centos 7

On my virtual-box machine (Centos 7) I tried to set the system environment variable via terminal like that:
export ADMIN_CONSOLE_HOME=" path to the folder"

and got the system environment variable in my Java code:
System.getenv("ADMIN_CONSOLE_HOME")

However, it didn`t help and returned NULL. Using Google-power I found out the solution how to set variables in Linux OS.
In my case, I added the following record to /root/.profile:
export ADMIN_CONSOLE_HOME=" path to the folder"

And after reboot all was fine.