Translate

Wednesday, February 29, 2012

Java - NoClassDefFoundError

Usually when you get an error telling you that a class cannot be found it really means that the class cannot be found. In my case I received this error because I was trying to run a Tomcat app from within Eclipse and the project I was running is referencing another project:

The error message said:
    java.lang.NoClassDefFoundError: Lcom/dataSpace/dataRecord/TableRecord;

I new that the class, TableRecord, is in the referenced project. To fix the problem I just had to add the refernced project to the DevLoader:

Thursday, February 23, 2012

SharePoint 2010 - Could not allocate space for object

The day was going along great when all of a sudden a lot of users were experiencing problems with our SharePoint site. I checked the SharePoint log file using the ULS viewer and with the correlation id from one of the errors I found this entry:

System.Data.SqlClient.SqlException: Could not allocate space for object 'dbo.AllUserData'.'AllUserData_ParentId' in database 'Insite_Content' because the 'PRIMARY' filegroup is full. Create disk space by deleting unneeded files, dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlDataReader.HasMoreRows() at System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout) at System.Data.SqlClient.SqlDataReader.NextResult() at Microsoft.SharePoint.SPSqlClient.ExecuteQueryInternal(Boolean retryfordeadlock) at Microsoft.SharePoint.SPSqlClient.ExecuteQuery(Boolean retryfordeadlock)

Turns out our SQL server is configured to do a daily backup to the same drive as the SQL database files and the drive was full after three months of backups. Isn't that just brilliant! There was no room for the database to grow. I removed some of the old backup files to free up some space and things were back to normal. Just to make sure this problem didn't happen again before we found the time to make this right, I added a cleanup task onto the backup maitenance job so that backup files older then 4 weeks would be deleted.

Friday, February 17, 2012

SharePoint 2010 - Add a Missing User Profile Property Attribute for Export

It was another one of those Thursdays! Yesterday I was trying to add a missing AD schema attribute to a User Profile Property for export using the AddNewExportMapping command in PowerShell which resulted in the following error:

Funny thing was that the attribute was still added to the property, but as an Import! In the end it was a good thing because I ended up learning more about the Synchronization Service Manager. Turns out that adding the attributes is a lot easier using this application and you get a nice view to confirm that they are indeed there! Here's how to do it. On your SharePoint server run the Synchronization Service Manager, miisclient.exe. In articles you will also find it referred to as SSM or the FIM client. It is located in the C:\Program Files\Microsoft Office Servers\14.0\Synchronization Service\UIShell folder.

Select your connection:

Then right click and select properties:

Select "Configure Attribute Flow":

Then select the appropriate group. In my case the "Data Source Attribute" with "Object Type" user" and "Metaverse Attribute" with "Object Type: person". Then in the "Build Attribute Flow" section select the "Data source attribute" and the corresponding "Metaverse attribute" and in the "Flow Direction" section select your desired direction settings:

When you have made your selections, click "New" to add the mapping.

Thursday, February 16, 2012

SharePoint 2010 - Reorder User Profile Properties

Changing the display order of profile properties in SharePoint is a real PITA. There are some scripts you can find on the web to make it easier, but from what I've read people have had mixed results using those scripts. A way that I found that is easy and definitely works is to change the value of the display order in the database table, ProfileSubtypePropertyAttributes, in the Profile database using SQL Manager.

The following SQL script will list the properties along with the display order.
SELECT TOP 1000 [ProfileSubtypeID]
      ,[ProfileSubtypePropertyAttributes].[PropertyID]
      ,[PropertyList].[PropertyName]
      ,[PropertyList].[isSection]
      ,[DisplayOrder]
FROM [Profile DB].[dbo].[ProfileSubtypePropertyAttributes]
join [Profile DB].[dbo].[PropertyList] on propertyList.propertyid = [ProfileSubtypePropertyAttributes].propertyid  where [ProfileSubtypeID] = 1
order by [DisplayOrder]

The script will give you a listing like this:
Displayorder

The following update script changes the display order of the property with the propertyID, 10013, to 5304. Note that the numbering for the DisplayOrder field does not have to be sequential. The screen shot above shows the property with the new display order value.
update [Profile DB].[dbo].[ProfileSubtypePropertyAttributes]
set DisplayOrder = 5304
where propertyID = 10013

Wednesday, February 15, 2012

SharePoint 2010 - New AD Property Not Displayed

If you add a new User Profile Property and it's coming from the Active Directory the property will not be displayed on the My Sites edit profile page until you do a profile synchronization.

Monday, February 13, 2012

Radio for a New Nation | Internews

For decades, radio waves have been the primary vehicle to disseminate information in Sudan, as in many places where literacy is low, electricity is inconsistent or uneven, and media options are few. But until eight years ago, most people in South Sudan did not have access to radio or any type of independent media.
Radio for a New Nation | Internews

Friday, February 10, 2012

Local Afghan Media Institute Launched | Internews

Institute offers first-ever two-year media diploma course and releases first Media Directory for Afghanistan.
Local Afghan Media Institute Launched | Internews

Microsoft Virtual Labs - Unable to register person

This morning I tried to go to one of the Microsoft virtual labs. You can find them here. This site is a great resource. Anyway, when I click on the "Launch Virtual Lab" button everything ran fine until just after the "Checking ActiveX Control" part at the end when I received a message saying "Unable to register person". I went back top the launch screen and clicked "View System Requirements:

then clicked on Firewall:

The start-up of the lab launched just fine!

Wednesday, February 8, 2012

Microsoft Silverlight Video Will Not Play

I was attempting to watch a video on SharePoint 2010 PerformancePoint Services and couldn't get the video to play on any browsers, IE, Firefox, Chrome, or Opera. In my case the problem was caused by the sound settings on my laptop, which I discovered by trying to play a Flash video on YouTube. The Flash videos played but there was no sound. Changing my sound settings in the Control Panel fixed the problem and the Silverlight videos played. It's odd that a bad sound setting causes the Silverlight videos to not play at all.

Sunday, February 5, 2012

MyBatis – Database Change Logging

Here's how I handle recording database record changes. Changes are logged to a database table with the old values, new values, and ID of the user that made the change.

I set up an abstract Java class, StandardTable, that is used to base the classes for the main database tables:

/**
 * 
 * @author rgolebiowski
 *All of the main table classes are extended from this class.
 *All of the main database tables use ID field for the primary key
 *
 */
public abstract class StandardTable {
    private Integer ID;
    
    public Integer getID() {
        return ID;
    }

    public void setID(Integer ID) {
        this.ID = ID;
    } 
}


All of the Java classes for the main tables are extended from StandardTable. Example:

/**
 * 
 * @author rgolebiowski
 *Model for the AppTable table
 *
 */
public class AppTable extends StandardTable implements Serializable{


I set up an abstract Java class, TableRecord, to encapsulate standard methods for reading and saving StandardTable records:

/**
 * Abstract class for reading in and saving (insert or update) a record
 * @author rgolebiowski
 *
 */
public abstract class TableRecord {
 protected StandardTable tblRecord;//record being viewed or edited
 
 public abstract void loadRecord(Integer id);
 public abstract void saveRecord(AppUser appUser);
 
 public Object getTblRecord() {
  return tblRecord;
 }

 public void setTblRecord(Object tblRecord) {
  this.tblRecord = (StandardTable) tblRecord;
 }
}


All of the Java classes for viewing and editing records from the main tables are extended from TableRecord . Example:

/**
 * TableRecord for the AppTable database
 * @author rgolebiowski
 *
 */
public class AppTableRecord extends TableRecord {
 
 public AppTableRecord(){  
 }
 
 public AppTableRecord(AppTable tblRecord){
  this.setTblRecord(tblRecord);
 }

 /**
  * @param id: Record ID for the record to be loaded
  */
 public void loadRecord(Integer id) {
  GenericDataService genService = new GenericDataService("AppTableMapper");
  this.setTblRecord(genService.getByID(id));
 }

 /**
  * @param appUser: User that is updating the table
  */
 public void saveRecord(AppUser appUser) {
   try {
     //Switch MyBatis to map to the AppTAble database
     GenericDataService genService = new GenericDataService("AppTableMapper");
     //get the current record
     Object current = genService.getByID(((AppTable) this.tblRecord).getID());
     //log changes
     LogChange.log(appUser.getUserName(), current, this.tblRecord); 
     //if this is a current record then update
     if(((AppTable) this.getTblRecord()).getID() != null){
       genService.updateByID(this.getTblRecord());
     }
     else{
       //do an insert an set the record ID with the returned record ID
       this.setTblRecord(genService.insert(this.getTblRecord()));
     }
   } catch (IntrospectionException e) {
    e.printStackTrace();
   } catch (IllegalAccessException e) {
    e.printStackTrace();
   } catch (InvocationTargetException e) {
    e.printStackTrace();
   }
 }
}


Class for logging the database changes:

/**
 * Logger for databases changes
 * @author rgolebiowski
 *
 */
public class LogChange {

 /**
  * Constructs the string used to log the database changes
  * @param userID: UserID of the user making the change
  * @param bOld: Old object
  * @param bNew: New object
  * @throws IntrospectionException
  * @throws IllegalAccessException
  * @throws InvocationTargetException
  */
 public static void log(String userID, Object bOld, Object bNew) throws IntrospectionException, IllegalAccessException, InvocationTargetException {
    String res = "";//String to hold the change record
    boolean changed = false;
    try {
   if(bOld != null){ //if this is an update
       BeanInfo beanInfo = Introspector.getBeanInfo(bOld.getClass());
       res = bOld.getClass().getSimpleName() + " - ";
       //loop and compare old values with new values and add them to our string if they are changed
       for (PropertyDescriptor prop : beanInfo.getPropertyDescriptors()) {
           Method getter = prop.getReadMethod();
           Object vOld = getter.invoke(bOld); //old value
           Object vNew = getter.invoke(bNew); //new value
           if (vOld == vNew || (vOld != null && vOld.equals(vNew))) {
             continue;
           }
           changed = true;
           res = res + "(" + prop.getName()  + ", " +  vOld  + ", " + vNew + ")";
       }
     }
     else{//this is a new record
           changed = true;     
    BeanInfo beanInfo = Introspector.getBeanInfo(bNew.getClass());
    res = bNew.getClass().getSimpleName() + " - "; 
    //loop and create the string to log the new record
    for (PropertyDescriptor prop : beanInfo.getPropertyDescriptors()) {
      if(prop.getName().equals("class")) continue;       
      Method getter = prop.getReadMethod();
      Object vNew = getter.invoke(bNew);
      if (vNew != null) {
         res = res + "(" + prop.getName()  + ", " + vNew + ")";
      }
    }  
     }
     if (changed){
        logToDB(userID, res);
     }
  }
  catch (IllegalArgumentException e) {
    e.printStackTrace();
  }
  }
   
   /**
    * Saves the record to the database
    * @param userID: UserID of the user making the change
    * @param message: This string contains the changes
    */
   private static void logToDB(String userID, String message){
  ChangeLog changeLog = new ChangeLog();
  changeLog.setUserID(userID);
  changeLog.setMessage(message);
  SqlSessionFactory sqlSessionFactory = MyBatisConnectionFactory_INform.getSqlSessionFactory();
  SqlSession session = sqlSessionFactory.openSession();
  try {
      session.insert("ChangeLogMapper.insert", changeLog);
      session.commit();
  } finally {
      session.close();
  } 
   }
}


Then in my Strusts action I just have a simple method that calls saveRecord for my class to save the record to the database and record the changes. I just save it and forget about it!

    /**
     * Used to save the record to the database
     * @return SUCCESS
     * @throws Exception
     */
    public String saveRecord() throws Exception {
     this.tableRecord.saveRecord((AppUser) SessionService.getAttributeFromSession(request, SessionService.AppUser));
     this.resMsg = "Record saved.";
     return SUCCESS;
    }


The SQL script to create the ChangeLog database:
CREATE TABLE [dbo].[ChangeLog](
 [ID] [int] IDENTITY(1,1) NOT NULL,
 [Date] [datetime] NULL,
 [UserID] [varchar](50) NULL,
 [Message] [varchar](max) NULL,
 CONSTRAINT [PK_ChangeLog] PRIMARY KEY CLUSTERED 
(
 [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[ChangeLog] ADD  CONSTRAINT [DF_ChangeLog_Date]  DEFAULT (getdate()) FOR [Date]
GO



Microsoft Office Outlook Hotmail Connector

Just discovered this connector for Outlook. If you use Outlook and have a Hotmail account this is a nice add-on to have.
Microsoft Office Outlook Hotmail Connector overview - Outlook - Office.com

Saturday, February 4, 2012

Windows Live Writer

This is a test post to my Blog using Windows Live Writer. You can get it at Windows Live Essentials.

SharePoint 2010 - Web Services Root Site

If you look at your sites in IIS Manager you will see the root site. This site provides some services for SharePoint such as the Security Token Service on SSL enabled, site search, and My Sites. SharePoint handles turning this site on or off as needed so you may see this site turned off. SharePoint does a good job of handling this in general but in some cases this site could get turned off inadvertantly and you may get and error in the SharePoint  Logs such as

Could not connect to http://localhost:32843/SecurityTokenServiceApplication/securitytoken.svc

on SSL enable sites or a message such as

"Error: The Security Token Service is not available. The Security Token Service is not issuing tokens. The service could be malfunctioning or in a bad state."

in health analysis.