You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jackrabbit.apache.org by "Stephane Landelle (JIRA)" <ji...@apache.org> on 2008/10/15 15:35:44 UTC

[jira] Created: (JCR-1813) Invalid journal records during XATransactions

Invalid journal records during XATransactions
---------------------------------------------

                 Key: JCR-1813
                 URL: https://issues.apache.org/jira/browse/JCR-1813
             Project: Jackrabbit
          Issue Type: Bug
          Components: clustering
            Reporter: Stephane Landelle
            Priority: Critical


During the prepare phase of a XATransaction, XAItemStateManager.prepare calls ShareItemStageManager.beginUpdate that, in case of a ClusterNode, calls ClusterNode.updatePrepared that does a ChangeLogRecord.write().

This last method is located in ClusterRecord and systematically write the begin and the end of the journal record.

As a consequence, useless corrupted records are written in the journal everytime a transaction ends without jackrabbit update! This causes polution of the journal, as other cluster nodes try to sync with the corrupted updates and fail doing so as ClusterRecordDeserializer can't deserialize it (the record identifier is empty).

ChangeLogRecord (and even other ClusterRecord implementations too) should only write if there's effective updates.

I propose the following solution:
*) add the following method in Changelog so clients can know if there's effective updates:
    public boolean hasUpdates() {
    	return !(addedStates.isEmpty() && modifiedStates.isEmpty() && deletedStates.isEmpty() && modifiedRefs.isEmpty());
    }

*) change ClusterRecord with:
    public final void write() throws JournalException {
    	
    	if (hasUpdates()) {
	        record.writeString(workspace);
	        doWrite();
	        record.writeChar(END_MARKER);
    	}
    }
    
    protected abstract boolean hasUpdates();

*) implement hasUpdates for every ClusterRecord implementation:
 ----> ChangeLogRecord:
    protected boolean hasUpdates() {
    	return changes.hasUpdates() || !events.isEmpty();
    }
 ----> LockRecord and NamespaceRecord:
    protected boolean hasUpdates() {
    	return true;
    }

 ----> NodeTypeRecord:
    protected boolean hasUpdates() {
    	return !collection.isEmpty();
    }

Best regards,

Stephane Landelle

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


Re: [jira] Commented: (JCR-1813) Invalid journal records during XATransactions

Posted by Ian Boston <ie...@tfd.co.uk>.
Ok, I will try 1.5 again.
Thanks
Ian

On 5 Mar 2009, at 08:36, Jukka Zitting wrote:

> Hi,
>
> On Wed, Mar 4, 2009 at 6:19 PM, Ian Boston (JIRA) <ji...@apache.org>  
> wrote:
>> Will this get applied back to 1.4 ?
>
> There are currently no plans for another 1.4.x release.
>
>> I also tried 1.5, but it doesn't appear stable enough yet,
>
> My experience is that 1.5 is notably more stable than 1.4, is there a
> particular reason why you'd think otherwise? The major new features in
> 1.5 are related to access control and other new JSR 283 features. All
> JCR 1.0 features have only been incrementally improved since 1.4, and
> I haven't seen many regressions.
>
> We had some configuration troubles with the 1.5 upgrade, but all those
> issues should be covered already in 1.5.2.
>
> BR,
>
> Jukka Zitting


Re: [jira] Commented: (JCR-1813) Invalid journal records during XATransactions

Posted by Jukka Zitting <ju...@gmail.com>.
Hi,

On Wed, Mar 4, 2009 at 6:19 PM, Ian Boston (JIRA) <ji...@apache.org> wrote:
> Will this get applied back to 1.4 ?

There are currently no plans for another 1.4.x release.

> I also tried 1.5, but it doesn't appear stable enough yet,

My experience is that 1.5 is notably more stable than 1.4, is there a
particular reason why you'd think otherwise? The major new features in
1.5 are related to access control and other new JSR 283 features. All
JCR 1.0 features have only been incrementally improved since 1.4, and
I haven't seen many regressions.

We had some configuration troubles with the 1.5 upgrade, but all those
issues should be covered already in 1.5.2.

BR,

Jukka Zitting

[jira] Commented: (JCR-1813) Invalid journal records during XATransactions

Posted by "Ian Boston (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/JCR-1813?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12679022#action_12679022 ] 

Ian Boston commented on JCR-1813:
---------------------------------

Ignore my previous comment, I have a workarround in the form of a custom (ugly) AppendRecord 
For anyone else with the same problem it can be found at https://source.sakaiproject.org/contrib/k2/trunk/kernel/src/main/java/org/sakaiproject/kernel/jcr/jackrabbit/journal/ until the 1.4.x series gets updated or we move to 1.5.

> Invalid journal records during XATransactions
> ---------------------------------------------
>
>                 Key: JCR-1813
>                 URL: https://issues.apache.org/jira/browse/JCR-1813
>             Project: Jackrabbit Content Repository
>          Issue Type: Bug
>          Components: clustering, jackrabbit-core
>            Reporter: Stephane Landelle
>            Assignee: Jukka Zitting
>            Priority: Critical
>             Fix For: 1.5.0
>
>
> During the prepare phase of a XATransaction, XAItemStateManager.prepare calls ShareItemStageManager.beginUpdate that, in case of a ClusterNode, calls ClusterNode.updatePrepared that does a ChangeLogRecord.write().
> This last method is located in ClusterRecord and systematically write the begin and the end of the journal record.
> As a consequence, useless corrupted records are written in the journal everytime a transaction ends without jackrabbit update! This causes polution of the journal, as other cluster nodes try to sync with the corrupted updates and fail doing so as ClusterRecordDeserializer can't deserialize it (the record identifier is empty).
> ChangeLogRecord (and even other ClusterRecord implementations too) should only write if there's effective updates.
> I propose the following solution:
> *) add the following method in Changelog so clients can know if there's effective updates:
>     public boolean hasUpdates() {
>     	return !(addedStates.isEmpty() && modifiedStates.isEmpty() && deletedStates.isEmpty() && modifiedRefs.isEmpty());
>     }
> *) change ClusterRecord with:
>     public final void write() throws JournalException {
>     	
>     	if (hasUpdates()) {
> 	        record.writeString(workspace);
> 	        doWrite();
> 	        record.writeChar(END_MARKER);
>     	}
>     }
>     
>     protected abstract boolean hasUpdates();
> *) implement hasUpdates for every ClusterRecord implementation:
>  ----> ChangeLogRecord:
>     protected boolean hasUpdates() {
>     	return changes.hasUpdates() || !events.isEmpty();
>     }
>  ----> LockRecord and NamespaceRecord:
>     protected boolean hasUpdates() {
>     	return true;
>     }
>  ----> NodeTypeRecord:
>     protected boolean hasUpdates() {
>     	return !collection.isEmpty();
>     }
> Best regards,
> Stephane Landelle

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (JCR-1813) Invalid journal records during XATransactions

Posted by "Ian Boston (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/JCR-1813?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12678795#action_12678795 ] 

Ian Boston commented on JCR-1813:
---------------------------------

Will this get applied back to 1.4 ?

I have tried Extending/Replacing ClusterNode to stop it emitting empty journal records with JTA transactions, and because of all the protected, final methods, its not possible. I haven't tried aspects yet, but dont really want to, and analyzing the byte stream going into the DB is just going to be a pain.

It would be a shame to run from patched/forked version of Jackrabbit.

I also tried 1.5, but it doesn't appear stable enough yet,


> Invalid journal records during XATransactions
> ---------------------------------------------
>
>                 Key: JCR-1813
>                 URL: https://issues.apache.org/jira/browse/JCR-1813
>             Project: Jackrabbit Content Repository
>          Issue Type: Bug
>          Components: clustering, jackrabbit-core
>            Reporter: Stephane Landelle
>            Assignee: Jukka Zitting
>            Priority: Critical
>             Fix For: 1.5.0
>
>
> During the prepare phase of a XATransaction, XAItemStateManager.prepare calls ShareItemStageManager.beginUpdate that, in case of a ClusterNode, calls ClusterNode.updatePrepared that does a ChangeLogRecord.write().
> This last method is located in ClusterRecord and systematically write the begin and the end of the journal record.
> As a consequence, useless corrupted records are written in the journal everytime a transaction ends without jackrabbit update! This causes polution of the journal, as other cluster nodes try to sync with the corrupted updates and fail doing so as ClusterRecordDeserializer can't deserialize it (the record identifier is empty).
> ChangeLogRecord (and even other ClusterRecord implementations too) should only write if there's effective updates.
> I propose the following solution:
> *) add the following method in Changelog so clients can know if there's effective updates:
>     public boolean hasUpdates() {
>     	return !(addedStates.isEmpty() && modifiedStates.isEmpty() && deletedStates.isEmpty() && modifiedRefs.isEmpty());
>     }
> *) change ClusterRecord with:
>     public final void write() throws JournalException {
>     	
>     	if (hasUpdates()) {
> 	        record.writeString(workspace);
> 	        doWrite();
> 	        record.writeChar(END_MARKER);
>     	}
>     }
>     
>     protected abstract boolean hasUpdates();
> *) implement hasUpdates for every ClusterRecord implementation:
>  ----> ChangeLogRecord:
>     protected boolean hasUpdates() {
>     	return changes.hasUpdates() || !events.isEmpty();
>     }
>  ----> LockRecord and NamespaceRecord:
>     protected boolean hasUpdates() {
>     	return true;
>     }
>  ----> NodeTypeRecord:
>     protected boolean hasUpdates() {
>     	return !collection.isEmpty();
>     }
> Best regards,
> Stephane Landelle

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Reopened: (JCR-1813) Invalid journal records during XATransactions

Posted by "Jukka Zitting (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/JCR-1813?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jukka Zitting reopened JCR-1813:
--------------------------------


Hmm, you're right. I was just thinking about the original use case where a distributed transaction that has no Jackrabbit changes is committed.

Reopening this issue so I remember to look at it more before releasing 1.5.0. I guess it would be a good to set up a clustered test case for the following code:

    Session session = repository.login(...);
    try {
        session.save();
    } finally {
        session.logout();
    }

This should at least not cause cluster nodes to fail. It would be nice if it also didn't result in any journal entries.

> Invalid journal records during XATransactions
> ---------------------------------------------
>
>                 Key: JCR-1813
>                 URL: https://issues.apache.org/jira/browse/JCR-1813
>             Project: Jackrabbit
>          Issue Type: Bug
>          Components: clustering, jackrabbit-core
>            Reporter: Stephane Landelle
>            Assignee: Jukka Zitting
>            Priority: Critical
>             Fix For: 1.5.0
>
>
> During the prepare phase of a XATransaction, XAItemStateManager.prepare calls ShareItemStageManager.beginUpdate that, in case of a ClusterNode, calls ClusterNode.updatePrepared that does a ChangeLogRecord.write().
> This last method is located in ClusterRecord and systematically write the begin and the end of the journal record.
> As a consequence, useless corrupted records are written in the journal everytime a transaction ends without jackrabbit update! This causes polution of the journal, as other cluster nodes try to sync with the corrupted updates and fail doing so as ClusterRecordDeserializer can't deserialize it (the record identifier is empty).
> ChangeLogRecord (and even other ClusterRecord implementations too) should only write if there's effective updates.
> I propose the following solution:
> *) add the following method in Changelog so clients can know if there's effective updates:
>     public boolean hasUpdates() {
>     	return !(addedStates.isEmpty() && modifiedStates.isEmpty() && deletedStates.isEmpty() && modifiedRefs.isEmpty());
>     }
> *) change ClusterRecord with:
>     public final void write() throws JournalException {
>     	
>     	if (hasUpdates()) {
> 	        record.writeString(workspace);
> 	        doWrite();
> 	        record.writeChar(END_MARKER);
>     	}
>     }
>     
>     protected abstract boolean hasUpdates();
> *) implement hasUpdates for every ClusterRecord implementation:
>  ----> ChangeLogRecord:
>     protected boolean hasUpdates() {
>     	return changes.hasUpdates() || !events.isEmpty();
>     }
>  ----> LockRecord and NamespaceRecord:
>     protected boolean hasUpdates() {
>     	return true;
>     }
>  ----> NodeTypeRecord:
>     protected boolean hasUpdates() {
>     	return !collection.isEmpty();
>     }
> Best regards,
> Stephane Landelle

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (JCR-1813) Invalid journal records during XATransactions

Posted by "Stephane Landelle (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/JCR-1813?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12640844#action_12640844 ] 

Stephane Landelle commented on JCR-1813:
----------------------------------------

Hello Jukka,

Are you sure the problem is specific to XA transactions?

I guess the same problem happens with local transactions. One might not have
actual updates to commit, depending on the business code executed inside the
transaction.

So I think every SharedItemStateManager is impacted and that testing if the
ChangeLog has actual updates should be done in the core methods.

Am I wrong somewhere?

Best regards,

Stephane Landelle

2008/10/19 Jukka Zitting (JIRA) <ji...@apache.org>



> Invalid journal records during XATransactions
> ---------------------------------------------
>
>                 Key: JCR-1813
>                 URL: https://issues.apache.org/jira/browse/JCR-1813
>             Project: Jackrabbit
>          Issue Type: Bug
>          Components: clustering, jackrabbit-core
>            Reporter: Stephane Landelle
>            Assignee: Jukka Zitting
>            Priority: Critical
>             Fix For: 1.5.0
>
>
> During the prepare phase of a XATransaction, XAItemStateManager.prepare calls ShareItemStageManager.beginUpdate that, in case of a ClusterNode, calls ClusterNode.updatePrepared that does a ChangeLogRecord.write().
> This last method is located in ClusterRecord and systematically write the begin and the end of the journal record.
> As a consequence, useless corrupted records are written in the journal everytime a transaction ends without jackrabbit update! This causes polution of the journal, as other cluster nodes try to sync with the corrupted updates and fail doing so as ClusterRecordDeserializer can't deserialize it (the record identifier is empty).
> ChangeLogRecord (and even other ClusterRecord implementations too) should only write if there's effective updates.
> I propose the following solution:
> *) add the following method in Changelog so clients can know if there's effective updates:
>     public boolean hasUpdates() {
>     	return !(addedStates.isEmpty() && modifiedStates.isEmpty() && deletedStates.isEmpty() && modifiedRefs.isEmpty());
>     }
> *) change ClusterRecord with:
>     public final void write() throws JournalException {
>     	
>     	if (hasUpdates()) {
> 	        record.writeString(workspace);
> 	        doWrite();
> 	        record.writeChar(END_MARKER);
>     	}
>     }
>     
>     protected abstract boolean hasUpdates();
> *) implement hasUpdates for every ClusterRecord implementation:
>  ----> ChangeLogRecord:
>     protected boolean hasUpdates() {
>     	return changes.hasUpdates() || !events.isEmpty();
>     }
>  ----> LockRecord and NamespaceRecord:
>     protected boolean hasUpdates() {
>     	return true;
>     }
>  ----> NodeTypeRecord:
>     protected boolean hasUpdates() {
>     	return !collection.isEmpty();
>     }
> Best regards,
> Stephane Landelle

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (JCR-1813) Invalid journal records during XATransactions

Posted by "Stephane Landelle (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/JCR-1813?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12639880#action_12639880 ] 

Stephane Landelle commented on JCR-1813:
----------------------------------------

My bad, my patch writes null records instead of not writing them.

A better solution would consist in:

   - adding the hasUpdates method to ChangeLog
   - skipping begin and end in
   org.apache.jackrabbit.core.state.SharedItemStateManager$Update if local has
   no updates with somehing like:

            if (!local.hasUpdates()) {
                return;
            }

Sincerely,

Stephane Landelle

2008/10/15 Stephane Landelle (JIRA) <ji...@apache.org>



> Invalid journal records during XATransactions
> ---------------------------------------------
>
>                 Key: JCR-1813
>                 URL: https://issues.apache.org/jira/browse/JCR-1813
>             Project: Jackrabbit
>          Issue Type: Bug
>          Components: clustering
>            Reporter: Stephane Landelle
>            Priority: Critical
>
> During the prepare phase of a XATransaction, XAItemStateManager.prepare calls ShareItemStageManager.beginUpdate that, in case of a ClusterNode, calls ClusterNode.updatePrepared that does a ChangeLogRecord.write().
> This last method is located in ClusterRecord and systematically write the begin and the end of the journal record.
> As a consequence, useless corrupted records are written in the journal everytime a transaction ends without jackrabbit update! This causes polution of the journal, as other cluster nodes try to sync with the corrupted updates and fail doing so as ClusterRecordDeserializer can't deserialize it (the record identifier is empty).
> ChangeLogRecord (and even other ClusterRecord implementations too) should only write if there's effective updates.
> I propose the following solution:
> *) add the following method in Changelog so clients can know if there's effective updates:
>     public boolean hasUpdates() {
>     	return !(addedStates.isEmpty() && modifiedStates.isEmpty() && deletedStates.isEmpty() && modifiedRefs.isEmpty());
>     }
> *) change ClusterRecord with:
>     public final void write() throws JournalException {
>     	
>     	if (hasUpdates()) {
> 	        record.writeString(workspace);
> 	        doWrite();
> 	        record.writeChar(END_MARKER);
>     	}
>     }
>     
>     protected abstract boolean hasUpdates();
> *) implement hasUpdates for every ClusterRecord implementation:
>  ----> ChangeLogRecord:
>     protected boolean hasUpdates() {
>     	return changes.hasUpdates() || !events.isEmpty();
>     }
>  ----> LockRecord and NamespaceRecord:
>     protected boolean hasUpdates() {
>     	return true;
>     }
>  ----> NodeTypeRecord:
>     protected boolean hasUpdates() {
>     	return !collection.isEmpty();
>     }
> Best regards,
> Stephane Landelle

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Resolved: (JCR-1813) Invalid journal records during XATransactions

Posted by "Jukka Zitting (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/JCR-1813?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jukka Zitting resolved JCR-1813.
--------------------------------

       Resolution: Fixed
    Fix Version/s: 1.5.0
         Assignee: Jukka Zitting

Resolved in revision 705938. Thanks for the good report and proposed fix!

I added the ChangeLog.hasUpdates() method as proposed, but used it already in XAItemStateManager instead of SharedItemStateManager to avoid as much extra processing as possible.

> Invalid journal records during XATransactions
> ---------------------------------------------
>
>                 Key: JCR-1813
>                 URL: https://issues.apache.org/jira/browse/JCR-1813
>             Project: Jackrabbit
>          Issue Type: Bug
>          Components: clustering, jackrabbit-core
>            Reporter: Stephane Landelle
>            Assignee: Jukka Zitting
>            Priority: Critical
>             Fix For: 1.5.0
>
>
> During the prepare phase of a XATransaction, XAItemStateManager.prepare calls ShareItemStageManager.beginUpdate that, in case of a ClusterNode, calls ClusterNode.updatePrepared that does a ChangeLogRecord.write().
> This last method is located in ClusterRecord and systematically write the begin and the end of the journal record.
> As a consequence, useless corrupted records are written in the journal everytime a transaction ends without jackrabbit update! This causes polution of the journal, as other cluster nodes try to sync with the corrupted updates and fail doing so as ClusterRecordDeserializer can't deserialize it (the record identifier is empty).
> ChangeLogRecord (and even other ClusterRecord implementations too) should only write if there's effective updates.
> I propose the following solution:
> *) add the following method in Changelog so clients can know if there's effective updates:
>     public boolean hasUpdates() {
>     	return !(addedStates.isEmpty() && modifiedStates.isEmpty() && deletedStates.isEmpty() && modifiedRefs.isEmpty());
>     }
> *) change ClusterRecord with:
>     public final void write() throws JournalException {
>     	
>     	if (hasUpdates()) {
> 	        record.writeString(workspace);
> 	        doWrite();
> 	        record.writeChar(END_MARKER);
>     	}
>     }
>     
>     protected abstract boolean hasUpdates();
> *) implement hasUpdates for every ClusterRecord implementation:
>  ----> ChangeLogRecord:
>     protected boolean hasUpdates() {
>     	return changes.hasUpdates() || !events.isEmpty();
>     }
>  ----> LockRecord and NamespaceRecord:
>     protected boolean hasUpdates() {
>     	return true;
>     }
>  ----> NodeTypeRecord:
>     protected boolean hasUpdates() {
>     	return !collection.isEmpty();
>     }
> Best regards,
> Stephane Landelle

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Resolved: (JCR-1813) Invalid journal records during XATransactions

Posted by "Jukka Zitting (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/JCR-1813?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jukka Zitting resolved JCR-1813.
--------------------------------

    Resolution: Fixed

Added the hasUpdates condition for non-transactional updates in revision 708619.

Also, in revision 708609 I made the journal consumer handle such empty records more gracefully.

> Invalid journal records during XATransactions
> ---------------------------------------------
>
>                 Key: JCR-1813
>                 URL: https://issues.apache.org/jira/browse/JCR-1813
>             Project: Jackrabbit
>          Issue Type: Bug
>          Components: clustering, jackrabbit-core
>            Reporter: Stephane Landelle
>            Assignee: Jukka Zitting
>            Priority: Critical
>             Fix For: 1.5.0
>
>
> During the prepare phase of a XATransaction, XAItemStateManager.prepare calls ShareItemStageManager.beginUpdate that, in case of a ClusterNode, calls ClusterNode.updatePrepared that does a ChangeLogRecord.write().
> This last method is located in ClusterRecord and systematically write the begin and the end of the journal record.
> As a consequence, useless corrupted records are written in the journal everytime a transaction ends without jackrabbit update! This causes polution of the journal, as other cluster nodes try to sync with the corrupted updates and fail doing so as ClusterRecordDeserializer can't deserialize it (the record identifier is empty).
> ChangeLogRecord (and even other ClusterRecord implementations too) should only write if there's effective updates.
> I propose the following solution:
> *) add the following method in Changelog so clients can know if there's effective updates:
>     public boolean hasUpdates() {
>     	return !(addedStates.isEmpty() && modifiedStates.isEmpty() && deletedStates.isEmpty() && modifiedRefs.isEmpty());
>     }
> *) change ClusterRecord with:
>     public final void write() throws JournalException {
>     	
>     	if (hasUpdates()) {
> 	        record.writeString(workspace);
> 	        doWrite();
> 	        record.writeChar(END_MARKER);
>     	}
>     }
>     
>     protected abstract boolean hasUpdates();
> *) implement hasUpdates for every ClusterRecord implementation:
>  ----> ChangeLogRecord:
>     protected boolean hasUpdates() {
>     	return changes.hasUpdates() || !events.isEmpty();
>     }
>  ----> LockRecord and NamespaceRecord:
>     protected boolean hasUpdates() {
>     	return true;
>     }
>  ----> NodeTypeRecord:
>     protected boolean hasUpdates() {
>     	return !collection.isEmpty();
>     }
> Best regards,
> Stephane Landelle

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.