Rubrika: Written in English

  • OAuthLogin – beta testing

    No public interest, so I discontinued this project

    I have an idea of writing new website and I know that people do not like registrations. To maximize user involvement and participation I decided to support OAuth login technology which delegates authentication and authorization to different provider. In other words you can safely login with Google, Facebook and many other service accounts. I found Scribe library that helps Java developers but I realized that it is not such easy to start. So I decided to write a prototype first to learn all neccessary technologies in advance. And once it progressed and I put more effort in it I decided to make it public and open source.

    So there it is. It is beta release which improved user experience and fixed too broad privileges issue. It is standalone Java Enterprise application consisting of two modules: EJB and WAR. The users are persisted in database via JPA. The users can log with Google, Twitter and Facebook. I reconsider Microsoft account support as well. It is possible to log with one provider and then link other providers as well, so you can later choose any provider to log into same account.

    GitHub

     

  • Security by McAfee

    There is McAfee Endpoint Security running on my work computer. Yesterday I lost few hours with having it blocked by my computer. I turned the computer on in the morning but Endpoint Security (ES) did not accept my password with following message: Error EE0F0001: Token authentication parameters are incorrect. I was more carefull typing the password, I had to wait for a minute  but it failed again. The third attempt failed again (and pause doubled). Then I had to call to a service desk to unlock it via passphrase exchange. I was curios, if the error disappeared so I rebooted my computer,  typed carefully the password and the same problem occured again, but the wait time increased to 5 minutes.

    So I called helpdesk again, we went through the same procedure and he told me to change my windows password. I did and I printed neccessary materials, then I rebooted the computer and tried again – 15 minutes wait time and passwors was not still accepted. Fourth unlock procedure and guy from helpdesk told me that I need to wait at least half an hour after password change before rebooting computer to let McAfee Endpoint security sync new password. Fine, I did it again, finished some important work, verified in ES that authentical token was synced recently and rebooted notebook again. I typed my password and it told me that it is blocked for 30 minutes now! I called the helpdesk again and he told me that I had to switch off the computer to reset this pause counter. When I did, I could login in immediatelly.

    Well, friday was not very productive day. But i realized that to spoof McAfee’s security increasing pause you just need to turn the computer off.

  • Linking external directories to Google drive

    I recently started to use Google Drive desktop client on Windows. It created Disk Google in my home directory. Test was OK, but I realized one thing: there is no possibility to add a directory outside of this default directory. I was used to SugarSync where I had total control, which directory will be synchronized and I lacked this feature in Google Drive. Having strong Unix background I immediatelly had an idea to use symlinks. I knew there was such functionality in NFTS and after while I found junction command.

    The first attempt was unsuccessful. When I created symlink in my Google Drive directory pointing to the requested location, nothing happened. Google Drive completely ignored such directory. When I reversed the direction, it worked. So I had to move existing directory (AppData\Roaming\.purple\logs\ to synchronize IM conversations across multiple computers) to Google Drive and then create symlink on original location. That’s it.

    c:\Users\Leoš\AppData\Roaming\.purple>c:\bin\junction.exe logs "c:\Users\Leoš\Disk Google\pidgin\"
    
    Junction v1.06 - Windows junction creator and reparse point viewer
    Copyright (C) 2000-2010 Mark Russinovich
    Sysinternals - www.sysinternals.com
    
    Created: c:\Users\Leo?\AppData\Roaming\.purple\logs
    Targetted at: c:\Users\Leo?\Disk Google\pidgin"
  • Duplicate entry in a form

    I have seen several forms recently that requested user to enter some information twice. It makes sense to retype the password that user has chosen. It reduces a risk that user does typo and newly created account will be unaccessible. But these forms asked the user to retype his email address or existing password. The email address is displayed unlike password, so the risk of typo is quite small. But I can imagine that developer thinks that this email is so important to force the user to enter the same information twice. To retype existing password is totally useless. If the user enters his password incorrectly, just redisplay the form. Please when you design some form with duplicated entry of some field, ask yourself – is it really neccessary to bother the user?

  • Tips on installing MS SQL 2012 Express edition

    Well, I was once again forced to use another Microsoft product – their database this time. And it took me several hours to make it work, so I want to share some details in hope, that it will be helpfull to you.

    The installation was smooth but later I realized that I cannot contact this database from java. Why? TCP IP was disabled by default. This is very secure option, yet I can imagine more secure one – switch the computer off. Stop kidding. Open SQL Server Configuration Manager, open Network configuration from left tree and select Protocols node. There you need to enable TCP/IP protocol, open its properties dialog and change the property Enabled to true.

    TCP/IP protocol properties

    Dis is one half. Oh no, it is back! (Who does understand this joke?)

    If you try to connect this new database, you will fail again. MS SQL will play a game Guess my port with you. Ok, they have some naming service and some good reasons for this behaviour, but let keep things simple and switch off dynamic ports feature. Choose IP addresses tab. Either modify one concrete network interface or find the last section IP All. Delete value in the option TCP Dynamic Ports and set 1433 to the option TCP Port. Finally you have to restart MS SQL service.

    Default value with dynamic portupdated value to MS SQL default portRestarting MS SQL service

    Stop, we are not finished yet. You do not want to use your windows credentials and probably store them somewhere in configuration files, do you? So it is time to switch off Windows Authentication mode. Open MS SQL Management Studio, edit server properties, Security page particularly. There you need to select mixed mode – both SQL Server and Windows Authentication modes in Server authentication section.

    Selecting authentication mode

    And finally create some user with appropriate roles. It is neccessary to be DDL admin and DB owner for development purposes. Restart MS SQL

    Adding new user

    Some useful links I used:

    Blog bitcoin address: 1GQBYqZwiHT72UrLCCSv4j6WkK65FjTPJk

  • Working with complex database types in WebLogic

    My colleague asked me for help with a project, where java layer prepared data and passed it to a database layer, where PL/SQL functions awaited it. Some functions expected standard types like VARCHAR or NUMBER and implementation was smooth. But few functions expected complex database type on its input – table of types that reference other types. It took me some time to figure it out (StackOverflow question), how to prepare data and connection correctly. And I have learned several lessons I want to share in this article.

    Let me introduce the example I will present here. There is a table Person with attributes name, surname, age and flag vip. The package oracle_types has two methods: get and add. The get method returns Antonín Holý record, the add method will store new entry into Person table with flag vip set when there is a keyword ‚actor‘ set.

    CREATE TABLE PERSON (
        name    VARCHAR2(20),
        surname VARCHAR2(30),
        age     NUMBER(3),
        vip     CHAR(1)
    );
    
    CREATE OR REPLACE TYPE keyword_rec IS OBJECT (
        value VARCHAR2(20)
    );
    
    CREATE OR REPLACE TYPE keywords_rec IS TABLE OF keyword_rec;
    
    CREATE OR REPLACE TYPE person_rec IS OBJECT (
        name     VARCHAR2(20),
        surname  VARCHAR2(30),
        age      NUMBER(3),
        keywords keywords_rec
    );
    
    CREATE OR REPLACE PACKAGE oracle_types AS
      FUNCTION add(p_rec person_rec, p_message OUT VARCHAR2) RETURN PLS_INTEGER;
      FUNCTION get RETURN person_rec;
    end oracle_types;
    /
    
    CREATE OR REPLACE PACKAGE BODY oracle_types IS
      FUNCTION add(p_rec person_rec, p_message out varchar2) RETURN PLS_INTEGER IS
       v_vip NUMBER := 0;
      BEGIN
        FOR cur IN 1 .. p_rec.keywords.LAST
        LOOP
          IF p_rec.keywords(cur).value = 'actor' THEN
            v_vip := 1;
          END IF;
        END LOOP;
          IF v_vip > 0 THEN
            INSERT INTO PERSON(name,surname,age,vip) VALUES (p_rec.name, p_rec.surname, p_rec.age, '1');
          ELSE
            INSERT INTO PERSON(name,surname,age,vip) VALUES (p_rec.name, p_rec.surname, p_rec.age, '0');
          END IF;
       RETURN 1;
      END;
    
      FUNCTION get RETURN person_rec IS
       v_person person_rec;
       v_keywords keywords_rec;
      begin
        v_keywords := keywords_rec();
        v_keywords.EXTEND(2);
        v_keywords(1) := keyword_rec('scientist');
        v_keywords(2) := keyword_rec('inventor');
        v_person := person_rec('Antonin', 'Holy', 75, v_keywords);
        RETURN v_person;
      END;
    
    BEGIN
      NULL;
    end oracle_types;
    /
    
    declare
     v_result person_rec;
    begin
      v_result := oracle_types.get();
      dbms_output.put_line('name = '||v_result.name);
      dbms_output.put_line('surname = '||v_result.surname);
      dbms_output.put_line('age = '||v_result.age);
      for cur in 1 .. v_result.keywords.last
      loop
        dbms_output.put_line('keyword = '||v_result.keywords(cur).value);
      end loop;
    end;
    /

    The types must be public and they cannot be declared inside the package. Otherwise java will not see them. The java side will reside in WebLogic, so we need a remote interface for our business logic:

    @Remote
    public interface IOracleTest {
        public void performGet() throws Exception;
        public void performCall() throws Exception;
    }

    The stateless session bean implements this interface. It needs an access to database, so I declared datasource and let the application server to inject it.

    @Stateless(mappedName = "test/oracle")
    public class OracleTest implements IOracleTest {
        private static final Log log = LogFactory.getLog(OracleTest.class);
    
        @Resource(name = "jdbc/test")
        protected javax.sql.DataSource datasource;

    The data source is to be created in Services/Data Sources menu option and JNDI name must match java resource name.

    weblogic-ds

    I will describe add method, because it is more complex – you need to construct an object tree the way that Oracle database expects. You must register your types in database connection. If the type is not public and it is located in different schema than your JDBC connection uses, you must prefix it with schema name.

    conn = datasource.getConnection();
    ArrayDescriptor keywordsArrayDesc = ArrayDescriptor.createDescriptor("KEYWORDS_REC", conn);
    StructDescriptor personStructDesc = StructDescriptor.createDescriptor("PERSON_REC", conn);

    The next step is to create array for person’s keywords. We have two rows with single column for KEYWORDS_REC type. The dimensions must be exactly the same like in database, otherwise an exception will occur. You have to pass objects that Oracle understands: String, BigDecimal, java.sql.Date etc. It is painfull to investigate, which object it does not like, because Oracle exceptions does not contain any identification of invalid value (SQLException: Inconsistent java and sql object types).

    Object[][] keywordsAttribs = new Object[2][1];
    keywordsAttribs[0][0] = "actor";
    keywordsAttribs[1][0] = "producer";

    Ok, it is time to prepare object for database procedure call. The person consists of four columns, therefore we need to create array of four objects. The last column is the table of KEYWORD_REC types. So we instantiate Oracle ARRAY object with two dimensional array and identification of used type (ArrayDescriptor keywordsArrayDesc). And we put it all together into Oracle STRUCT, again with type identification passed by StructDescriptor.

    Object[] personAttribs = new Object[4];
    personAttribs[0] = "Christian";
    personAttribs[1] = "Bale";
    personAttribs[2] = 39;
    personAttribs[3] = new ARRAY(keywordsArrayDesc, conn, keywordsAttribs);
    STRUCT struct = new STRUCT(personStructDesc, conn, personAttribs);

    The last preparation step is to prepare database call. Our PL/SQL function returns two values, so we will specify their position. Again, if the position or returned type does not match database, SQLException will be raised.

    prepStmt = conn.prepareCall("{ ? = call oracle_types.add(?, ?)}");
    prepStmt.registerOutParameter(1, Types.INTEGER);
    prepStmt.registerOutParameter(3, Types.VARCHAR);
    prepStmt.setObject(2, struct);

    Finally we will execute the statement and get the out variables.

    prepStmt.execute();
    int returnCode = prepStmt.getInt(1);
    String message = prepStmt.getString(3);

    The get method is very similar and I will leave it uncommented. Just one note – you need to have orai8n.jar in your classpath otherwise UTF conversion will not occur and fetched string will be unreadable.

    conn = datasource.getConnection();
    cs = conn.prepareCall(sql);
    
    StructDescriptor keywordStructDesc = StructDescriptor.createDescriptor("KEYWORD_REC", conn);
    StructDescriptor personStructDesc = StructDescriptor.createDescriptor("PERSON_REC", conn);
    ResultSetMetaData metaData = personStructDesc.getMetaData();
    cs.registerOutParameter(1, Types.STRUCT, "PERSON_REC");
    cs.execute();
    
    STRUCT output;
    Object recordTmp = cs.getObject(1);
    if (recordTmp instanceof Struct){
        output = (oracle.sql.STRUCT)(((weblogic.jdbc.wrapper.Struct)recordTmp).unwrap(Class.forName("oracle.sql.STRUCT")));
    } else {
        output = (oracle.sql.STRUCT)recordTmp;
    }
    
    Object[] data = output.getAttributes();
    int idx = 1;
    for (Object tmp : data) {
        log.info(metaData.getColumnName(idx++) + " = " + tmp + ",---");
    }

    All the source code plus executable ear application is attached. To compile, you will need to provide listed jars.

    PS I am interested how portable JDBC implementation would look like. Please comment code differences in Java.

    Blog bitcoin address: 1GQBYqZwiHT72UrLCCSv4j6WkK65FjTPJk

  • Comments in this blog

    When I returned from my vacation, I realized there were 30 comments in my blog waiting for approval. Some were very easy to recognize as spam. But other looked naturally on the first read. Until I found that it is not probable that english reader would enjoy czech written story.

    Then there were comments to my english written story. They looked fine, but author had URL containg commercial keywords (louis vuiton, ray bean, social stocks ..) – I marked them as spam as well. Finally there were few remaining comments, where I had to open author URL and guess, if they were posted by person or spam software. Thank you for your comments, I like them. Sorry if I was wrong and removed your real comment.

    I will have to spend some time and search for better wordpress comments solution. Facebook comments might be safe against spammers but I do not want to limit my readers that do not use it. The current solution is too weak, some captcha filter is unfortunatelly neccessary.

    PS very nice web spam description