This is basically just a type matching issue.
TableColumn<S, T> defines a method setCellValueFactory(Callback<CellDataFeatures<S,T>, ObservableValue<T>> factory).
Since you have defined the column as a TableColumn<Configuration, Long>, its setCellValueFactory is expecting a Callback<CellDataFeatures<Configuration, Long>, ObservableValue<Long>> as the parameter; i.e. it is expecting something that defines a method
public ObservableValue<Long> call(CellDataFeatures<Configuration, Long> cellDataFeatures) ;
If you pass this as a lambda expression of the form
cellData -> <some expression>
then the compiler will infer that cellData is a CellDataFeatures<Configuration, Long> and will require that the expression evaluates to an ObservableValue<Long>.
So cellData.getValue() will evaluate to a Configuration, and if you define the age property in Configuration as a LongProperty, then of course cellData.getValue().ageProperty() evaluates to a LongProperty. This causes a type mismatch and the compiler complains. Remember that the compiler is expecting this expression to evaluate to an ObservableValue<Long>; as you observed LongProperty implements ObservableValue<Number>, not ObservableValue<Long>. Thus your expression evaluates to an ObservableValue<Number> instead of the required type of ObservableValue<Long>.
Both the fixes you mentioned work: changing the column to a TableColumn<Configuration, Number> works because the compiler is then expecting a lambda expression evaluating to an ObservableValue<Number> (which it is getting).
Calling asObject() on the LongProperty works too. As the Javadocs state, this method creates an ObjectProperty<Long> that is bidirectionally bound to the LongProperty. Since ObjectProperty<T> implements ObservableValue<T>, cellData.getValue().ageProperty().asObject() is an ObservableValue<Long> as required.