Encounter NotSerializableException error when using Spring MVC NamedParameterJdbcTemplate - spring-mvc

I'm using Spring MVC NamedParameterJdbcTemplate, when i call "userService.addAndSendAccountActivationEmail(user, request)" from controller, i got error. But if i don't use named parameter(like: private static final String ADD = "insert into user_(user_id, email, username, password, create_date, modified_date, status_) values(?, ?, ?, ?, ?, ?, ?)"), everything work fine for me.
When this line has been called on BaseDao "jdbcTemplate.getJdbcOperations().update(sql, param, keyHolder)", i see nothing in "param" object.
I've added "org.springframework.jdbc" level to track, see my error log below.
Any help will be greatly appreciated.
#Service("userService")
public class UserService implements Serializable {
private static final long serialVersionUID = 1L;
#Resource
private UserDao userDao;
#Transactional
public void addAndSendAccountActivationEmail(User user, HttpServletRequest request) throws SystemException {
add(user);
// sendAccountActivationEmail(user, request);
}
}
public class UserDao extends BaseDao {
*/
private static final long serialVersionUID = 1L;
public UserDao(NamedParameterJdbcTemplate jdbcTemplate) {
super(jdbcTemplate);
}
private static final String ADD = "insert into user_(user_id, email, username, password, create_date, modified_date, status_) values(:userId, :email, :username, :password, :createDate, :modifiedDate, :status)";
public void add(User user) throws SystemException {
long userId = updateForLongKey(ADD, user);
user.setUserId(userId);
}
}
public class BaseDao implements Serializable {
private static final long serialVersionUID = 1L;
protected NamedParameterJdbcTemplate jdbcTemplate;
protected BaseDao(NamedParameterJdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
protected <T> long updateForLongKey(final String sql,T t){
SqlParameterSource param = new BeanPropertySqlParameterSource(t);
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.getJdbcOperations().update(sql, param, keyHolder);
return keyHolder.getKey().longValue();
}
}
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [com.htws.account.service.UserService.addAndSendAccountActivationEmail]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [com.mchange.v2.c3p0.impl.NewProxyConnection#6589127] for JDBC transaction
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection#6589127] to manual commit
DEBUG: org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL update
DEBUG: org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL statement [insert into user_(user_id, email, username, password, create_date, modified_date, status_) values(:userId, :email, :username, :password, :createDate, :modifiedDate, :status)]
TRACE: org.springframework.jdbc.core.StatementCreatorUtils - Setting SQL statement parameter value: column index 1, parameter value [org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource#1dafb644], value class [org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource], SQL type unknown
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
INFO : org.springframework.jdbc.support.SQLErrorCodesFactory - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]
DEBUG: org.springframework.jdbc.support.SQLErrorCodesFactory - Looking up default SQLErrorCodes for DataSource [com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 5000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hge16h8tu21anplw8eof|6469cee6, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hge16h8tu21anplw8eof|6469cee6, idleConnectionTestPeriod -> 3000, initialPoolSize -> 10, jdbcUrl -> jdbc:mysql://localhost:3306/htws?useUnicode=true&characterEncoding=UTF-8, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 1800, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 50, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 10, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]]
DEBUG: org.springframework.jdbc.support.SQLErrorCodesFactory - Database product name cached for DataSource [com.mchange.v2.c3p0.ComboPooledDataSource#bd9f0537]: name is 'MySQL'
DEBUG: org.springframework.jdbc.support.SQLErrorCodesFactory - SQL error codes for 'MySQL' found
DEBUG: org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator - Unable to translate SQLException with Error code '0', will now try the fallback translator
DEBUG: org.springframework.jdbc.support.SQLStateSQLExceptionTranslator - Extracted SQL state class 'S1' from value 'S1009'
TRACE: org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCompletion synchronization
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection [com.mchange.v2.c3p0.impl.NewProxyConnection#6589127]
TRACE: org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCompletion synchronization
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection#6589127] after transaction
DEBUG: org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
ERROR: com.htws.account.web.UserController - PreparedStatementCallback; SQL [insert into user_(user_id, email, username, password, create_date, modified_date, status_) values(:userId, :email, :username, :password, :createDate, :modifiedDate, :status)]; Invalid argument value: java.io.NotSerializableException; nested exception is java.sql.SQLException: Invalid argument value: java.io.NotSerializableException
org.springframework.dao.TransientDataAccessResourceException: PreparedStatementCallback; SQL [insert into user_(user_id, email, username, password, create_date, modified_date, status_) values(:userId, :email, :username, :password, :createDate, :modifiedDate, :status)]; Invalid argument value: java.io.NotSerializableException; nested exception is java.sql.SQLException: Invalid argument value: java.io.NotSerializableException
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:107)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:603)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:812)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:868)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:876)
at com.htws.core.dao.BaseDao.updateForLongKey(BaseDao.java:34)
at com.htws.account.dao.UserDao.add(UserDao.java:86)
at com.htws.account.service.UserService.add(UserService.java:65)
at com.htws.account.service.UserService.addAndSendAccountActivationEmail(UserService.java:58)
at com.htws.account.service.UserService$$FastClassByCGLIB$$4b2f4817.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at com.htws.account.service.UserService$$EnhancerByCGLIB$$78d9a26a.addAndSendAccountActivationEmail(<generated>)
at com.htws.account.web.UserController.processRegister(UserController.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:64)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:409)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:680)
Caused by: java.sql.SQLException: Invalid argument value: java.io.NotSerializableException
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:988)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:974)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:919)
at com.mysql.jdbc.PreparedStatement.setSerializableObject(PreparedStatement.java:4412)
at com.mysql.jdbc.PreparedStatement.setObject(PreparedStatement.java:4083)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.setObject(NewProxyPreparedStatement.java:365)
at org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:365)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:217)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:145)
at org.springframework.jdbc.core.ArgPreparedStatementSetter.doSetValue(ArgPreparedStatementSetter.java:65)
at org.springframework.jdbc.core.ArgPreparedStatementSetter.setValues(ArgPreparedStatementSetter.java:46)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:816)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:812)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:587)
... 63 more
Caused by: java.io.NotSerializableException: org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
at com.mysql.jdbc.PreparedStatement.setSerializableObject(PreparedStatement.java:4401)
... 73 more

try to use NamedParameterJdbcTemplate instead of SqlParameterSource .
Jdbc template dont have method which uses a SqlParameterSource

Related

Getting a One-to-One Relation to work in Azure Appservice using EF Code First

I am having a hard time getting this to work, so maybe you can help me out here.
Technologies used
Xamarin.Forms
Azure App Service
Azure SQL
AzureMobileServices (MobileServiceClient, MobileServer)
Entity Framework Code First
Introduction
My Xamarin.Forms app is used by users with both a billing and a delivery address. The database scheme looks like this:
Users
Id
BillingAddress_Id
DeliveryAddress_Id
Addresses
Id
User_Id
When adding new addresses, I basically do something like that:
var user = await userService.GetUserByIdAsync(...);
var billingAddress = new Address
{
UserId = user.Id,
…
};
var deliveryAddress = new Address
{
UserId = user.Id,
…
}
user.BillingAddress = billingAddress;
user.DeliveryAddress = deliveryAddress;
await addressService.AddNewAddressAsync(billingAddress);
await addressService.AddNewAddressAsync(deliveryAddress);
await userService.UpdateUser(user);
AddNewAddressAsync is a service method that eventually makes the underlying repository create a new address like this:
public async Task<Address> CreateAsync(Address item)
{
await Addresses.InsertAsync(item);
return item;
}
With Addresses being an instance of the IMobileServiceTable interface instantiated like this:
private IMobileServiceTable<Address> Addresses
{
get
{
var table = App.Client.GetTable<Address>();
table.MobileServiceClient.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;
return table;
}
}
UpdateUser on the other hand is supposed to patch the existing user by triggering the underlying repository like this:
public async Task<User> PatchAsync(User item)
{
await Users.UpdateAsync(item);
return item;
}
With Users also being an instance of the IMobileServiceTable interface instantiated the very same way as Addresses before:
private IMobileServiceTable<User> Users
{
get
{
var table = App.Client.GetTable<User>();
table.MobileServiceClient.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.Objects;
return table;
}
}
On server side, this is what the controllers do:
AddressController
[Authorize]
public class AddressController : TableController<Address>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
var context = new AppContext();
DomainManager = new EntityDomainManager<Address>(context, Request);
}
public async Task<IHttpActionResult> PostAddress(Address address)
{
Address current = await InsertAsync(address);
return CreatedAtRoute("Tables", new { id = current.Id }, current);
}
...
}
UserController
[Authorize]
public class UserController : TableController<User>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
var context = new AppContext();
DomainManager = new EntityDomainManager<User>(context, Request);
}
public Task<User> PatchUser(string id, Delta<User> patch)
{
return UpdateAsync(id, patch);
}
…
}
Here is what is logged when executing the above code:
Insertion of the first address
Request: POST http://localhost:51546/tables/Address
{"$id":"1","id":null,...,"UserId":"8953d3deb9b2459796aa00f43d7416cb","User":null}
iisexpress.exe Information: 0 : Request, Method=POST, Url=http://localhost:51546/tables/Address, Message='http://localhost:51546/tables/Address'
...
iisexpress.exe Information: 0 : Message='Model state is valid. Values: address=SpenceAppService.DataObjects.Address', Operation=HttpActionBinding.ExecuteBindingAsync
...
INSERT [dbo].[Addresses]([Id], [UserId], ...)
VALUES (#0, #1, ...)
SELECT ...
FROM [dbo].[Addresses]
WHERE ##ROWCOUNT > 0 AND [Id] = #0
-- #0: '2a407222f6984052b90d233fa9935286' (Type = String, Size = 128)
-- #1: '8953d3deb9b2459796aa00f43d7416cb' (Type = String, Size = 128)
...
-- Executing asynchronously at 23.05.2019 13:22:10 +02:00
-- Completed in 7 ms with result: SqlDataReader
Committed transaction at 23.05.2019 13:22:11 +02:00
Closed connection at 23.05.2019 13:22:11 +02:00
...
iisexpress.exe Information: 0 : Response, Status=201 (Created), Method=POST, Url=http://localhost:51546/tables/Address, Message='Content-type='application/json; charset=utf-8', content-length=unknown'
...
Response: Created
{"userId":"8953d3deb9b2459796aa00f43d7416cb",...,"id":"2a407222f6984052b90d233fa9935286",...}
Insertion of the second address
Request: POST http://localhost:51546/tables/Address
{"$id":"1","id":null,...,"UserId":"8953d3deb9b2459796aa00f43d7416cb","User":null}
iisexpress.exe Information: 0 : Request, Method=POST, Url=http://localhost:51546/tables/Address, Message='http://localhost:51546/tables/Address'
...
iisexpress.exe Information: 0 : Message='Model state is valid. Values: address=SpenceAppService.DataObjects.Address', Operation=HttpActionBinding.ExecuteBindingAsync
...
INSERT [dbo].[Addresses]([Id], [UserId], ...)
VALUES (#0, #1, ...)
SELECT ...
FROM [dbo].[Addresses]
WHERE ##ROWCOUNT > 0 AND [Id] = #0
-- #0: 'a56e1ca3a7b341a39bc00d22772e39e5' (Type = String, Size = 128)
-- #1: '8953d3deb9b2459796aa00f43d7416cb' (Type = String, Size = 128)
...
-- Executing asynchronously at 23.05.2019 13:22:11 +02:00
-- Completed in 0 ms with result: SqlDataReader
Committed transaction at 23.05.2019 13:22:11 +02:00
Closed connection at 23.05.2019 13:22:11 +02:00
...
iisexpress.exe Information: 0 : Response, Status=201 (Created), Method=POST, Url=http://localhost:51546/tables/Address, Message='Content-type='application/json; charset=utf-8', content-length=unknown'
...
Response: Created
{"userId":"8953d3deb9b2459796aa00f43d7416cb",...,"id":"a56e1ca3a7b341a39bc00d22772e39e5",...}
Patch of the user
Request: PATCH http://localhost:51546/tables/User/8953d3deb9b2459796aa00f43d7416cb
{"$id":"1","id":"8953d3deb9b2459796aa00f43d7416cb",...,"BillingAddress":{"$id":"7","id":"2a407222f6984052b90d233fa9935286",...,"UserId":"8953d3deb9b2459796aa00f43d7416cb","User":null},"DeliveryAddress":{"$id":"8","id":"a56e1ca3a7b341a39bc00d22772e39e5",...,"UserId":"8953d3deb9b2459796aa00f43d7416cb","User":null}}
iisexpress.exe Information: 0 : Request, Method=PATCH, Url=http://localhost:51546/tables/User/8953d3deb9b2459796aa00f43d7416cb, Message='http://localhost:51546/tables/User/8953d3deb9b2459796aa00f43d7416cb'
...
iisexpress.exe Information: 0 : Message='Model state is valid. Values: id=8953d3deb9b2459796aa00f43d7416cb, patch=System.Web.Http.OData.Delta`1[SpenceAppService.DataObjects.User]', Operation=HttpActionBinding.ExecuteBindingAsync
...
Opened connection asynchronously at 23.05.2019 13:22:30 +02:00
SELECT
...
[Limit1].[Id] AS [Id],
...
[Limit1].[BillingAddress_Id] AS [BillingAddress_Id],
[Limit1].[DeliveryAddress_Id] AS [DeliveryAddress_Id]
FROM ( SELECT TOP (1)
[Extent1].[Id] AS [Id],
...
[Extent1].[BillingAddress_Id] AS [BillingAddress_Id],
[Extent1].[DeliveryAddress_Id] AS [DeliveryAddress_Id]
FROM [dbo].[Users] AS [Extent1]
WHERE [Extent1].[Id] = #p__linq__0
) AS [Limit1]
-- p__linq__0: '8953d3deb9b2459796aa00f43d7416cb' (Type = String, Size = 4000)
...
INSERT [dbo].[Addresses]([Id], [UserId], ...)
VALUES (#0, #1, ...)
SELECT ...
FROM [dbo].[Addresses]
WHERE ##ROWCOUNT > 0 AND [Id] = #0
-- #0: '2a407222f6984052b90d233fa9935286' (Type = String, Size = 128)
-- #1: '8953d3deb9b2459796aa00f43d7416cb' (Type = String, Size = 128)
...
-- Executing asynchronously at 23.05.2019 13:22:30 +02:00
-- Failed in 1 ms with error: Violation of PRIMARY KEY constraint 'PK_dbo.Addresses'. Cannot insert duplicate key in object 'dbo.Addresses'. The duplicate key value is (2a407222f6984052b90d233fa9935286).
The statement has been terminated.
...
The request could not be completed. (Conflict)
Problem
As you can see, while patching the user, the underlying method tries to also insert the addresses that actually have already been inserted, so the error message does perfectly make sense.
However, how do I get this to work?
When I don't insert the addresses first, they don't get ids from the server, so when the userService patches the user which in turn tries to insert the addresses (which then don't exist yet), I get an error message telling me, that the Id field (of the address) is required.
When I add Id fields for both BillingAddress and DeliveryAddress to the user object and skip setting the address fields before updating the user but set their respective ids instead (after inserting the addresses), everything works as expected.
However, I still seem to be missing the üoint, because I thought, Entity Framework should be able to handle all of this internally.
I do know, that working with Azure Appservice, Entity Framework, Code First, an ASP.NET MVC backend and dependent tables accessed by using the Azure Mobile Apps Client and Server API makes things different,... but I was not able to find samples that clearly show how to get this just right...
I also read about having to configure relations either by using fluent API or by decorating properties. However, even when doing nothing, it seems to me as if the framework is able to handle this by itself. For instance when adding the BillingAddressId property to the user data object on server side and executing an Add-Migration, the migration code contains foreign key constraints without me having to explicitly configure them:
public override void Up()
{
AddColumn("dbo.Users", "BillingAddressId", c => c.String(maxLength: 128));
AddColumn("dbo.Users", "DeliveryAddressId", c => c.String(maxLength: 128));
CreateIndex("dbo.Users", "BillingAddressId");
CreateIndex("dbo.Users", "DeliveryAddressId");
AddForeignKey("dbo.Users", "BillingAddressId", "dbo.Addresses", "Id");
AddForeignKey("dbo.Users", "DeliveryAddressId", "dbo.Addresses", "Id");
}
You're User entities aren't aware of the Address objects that were added to the DB. What you want to do is var entity = context.Users.Find(id); and update entity with what's in patch using either entity.Prop = patch.Prop; or using something like Automapper to update the entity and then call your UpdateAsync. This will make the context aware of the new changes made to your User entity and will have the foreign keys populated.
Hope this helps.

net.corda.core.flows.UnexpectedFlowEndException: Tried to access ended session SessionId(toLong=8223329095323268472) with empty buffer

i*m using Corda 4.0 RC1 and have a clone of the cash-issuer repository; there i have a Corda-ResponderFlow which should do a business test; currently it throws an exception; the flow is programmed in this way
class ReceiveBankAccount(val otherSession: FlowSession) : FlowLogic<Unit>() {
#Suspendable
override fun call() {
logger.info("Starting ReceiveBankAccount flow...")
val signedTransactionFlow = object : SignTransactionFlow(otherSession) {
#Suspendable
override fun checkTransaction(stx: SignedTransaction) = requireThat {
val bankAccountState = stx.tx.outputsOfType<BankAccountState>().single()
val result = getBankAccountStateByAccountNumber(bankAccountState.accountNumber, serviceHub)
if (result != null) {
val linearId = result.state.data.linearId
throw IllegalArgumentException("Bank account $bankAccountState already exists with linearId ($linearId).")
}
}
}
subFlow(signedTransactionFlow)
if (!serviceHub.myInfo.isLegalIdentity(otherSession.counterparty)) {
subFlow(ReceiveFinalityFlow(otherSession))
}
}
}
after the execution of the parent corda-flow AddBankAccount i get the following error net.corda.core.flows.UnexpectedFlowEndException: Tried to access ended session SessionId(toLong=8223329095323268472) with empty buffer
what do i wrong? can anybody help me?
my stack trace is
net.corda.core.flows.UnexpectedFlowEndException: Tried to access ended session SessionId(toLong=8017581909056924623) with empty buffer
at net.corda.node.services.statemachine.FlowStateMachineImpl.processEventsUntilFlowIsResumed(FlowStateMachineImpl.kt:161) ~[corda-node-4.0-RC01.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.suspend(FlowStateMachineImpl.kt:407) ~[corda-node-4.0-RC01.jar:?]
at net.corda.node.services.statemachine.FlowSessionImpl.receive(FlowSessionImpl.kt:67) ~[corda-node-4.0-RC01.jar:?]
at net.corda.node.services.statemachine.FlowSessionImpl.receive(FlowSessionImpl.kt:71) ~[corda-node-4.0-RC01.jar:?]
at net.corda.core.flows.SignTransactionFlow.call(CollectSignaturesFlow.kt:294) ~[corda-core-4.0-RC01.jar:?]
at net.corda.core.flows.SignTransactionFlow.call(CollectSignaturesFlow.kt:198) ~[corda-core-4.0-RC01.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:290) ~[corda-node-4.0-RC01.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:311) ~[corda-core-4.0-RC01.jar:?]
at com.r3.corda.finance.cash.issuer.service.flows.ReceiveBankAccount.call(ReceiveBankAccount.kt:31) ~[classes/:?]
at com.r3.corda.finance.cash.issuer.service.flows.ReceiveBankAccount.call(ReceiveBankAccount.kt:12) ~[classes/:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:228) ~[corda-node-4.0-RC01.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:45) ~[corda-node-4.0-RC01.jar:?]
at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_131]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_131]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_131]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_131]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[?:1.8.0_131]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[?:1.8.0_131]
at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63) ~[corda-node-4.0-RC01.jar:?]
#Suspendable
override fun call(): SignedTransaction {
logger.info("Starting AddBankAccount flow...")
val accountNumber = bankAccount.accountNumber
logger.info("Checking for existence of state for $bankAccount.")
val result = getBankAccountStateByAccountNumber(accountNumber, serviceHub)
if (result != null) {
val linearId = result.state.data.linearId
throw IllegalArgumentException("Bank account $accountNumber already exists with linearId ($linearId).")
}
logger.info("No state for $bankAccount. Adding it.")
progressTracker.currentStep = TX_BUILDING
val bankAccountState = bankAccount.toState(ourIdentity, verifier)
val notary = serviceHub.networkMapCache.notaryIdentities.first()
val verifierSsession = initiateFlow(bankAccountState.verifier)
// The node running this flow is always the only signer.
val command = Command(BankAccountContract.Add(), listOf(ourIdentity.owningKey))
val outputStateAndContract = StateAndContract(bankAccountState, BankAccountContract.CONTRACT_ID)
val unsignedTransaction = TransactionBuilder(notary = notary).withItems(command, outputStateAndContract)
progressTracker.currentStep = TX_SIGNING
val partiallySignedTransaction = serviceHub.signInitialTransaction(unsignedTransaction)
progressTracker.currentStep = TX_VERIFICATION
partiallySignedTransaction.verify(serviceHub)
progressTracker.currentStep = SIGS_GATHERING
val sessionsForFinality = if (serviceHub.myInfo.isLegalIdentity(bankAccountState.verifier)) emptyList() else listOf(verifierSsession)
val fullySignedTx = subFlow(CollectSignaturesFlow(partiallySignedTransaction, sessionsForFinality, SIGS_GATHERING.childProgressTracker()))
progressTracker.currentStep = VERIFYING_SIGS
fullySignedTx.verifyRequiredSignatures()
progressTracker.currentStep = FINALISATION
// Share the added bank account state with the verifier/issuer.
return subFlow(FinalityFlow(fullySignedTx, sessionsForFinality, FINALISATION.childProgressTracker()))
}
ERROR in InitiatorFlow:
flow start AddBankAccount bankAccount: { accountId: "12345", accountName: "Roger's Account", accountNumber: { sortCode: "442200" , accountNumber: "13371337", type: "uk" }, currency: "GBP" }, verifier: Issuer: exception: Collection contains no element matching the predicate.
Fri Jan 18 11:14:03 CET 2019>>> [ERROR] 11:14:03+0100 [pool-8-thread-2] command.CRaSHSession.execute - Error while evaluating request 'flow start AddBankAccount bankAccount: { accountId: "12345", accountName: "Roger's Account", accountNumber: { sortCode: "442200" , accountNumber: "13371337", type: "uk" }, currency: "GBP" }, verifier: Issuer' flow start AddBankAccount bankAccount: { accountId: "12345", accountName: "Roger's Account", accountNumber: { sortCode: "442200" , accountNumber: "13371337", type: "uk" }, currency: "GBP" }, verifier: Issuer: exception: Collection contains no element matching the predicate. [errorCode=hf0q78, moreInformationAt=https://errors.corda.net/OS/4.0-RC01/hf0q78]
WARNs in InitiatorFlow:
[WARN] 11:14:07+0100 [rpc-client-observation-pool-1] internal.RPCClientProxyHandler.onRemoval - A hot observable returned from an RPC was never subscribed to. This wastes server-side resources because it was queueing observations for retrieval. It is being closed now, but please adjust your code to call .notUsed() on the observable to close it explicitly. (Java users: subscribe to it then unsubscribe). If you aren't sure where the leak is coming from, set -Dnet.corda.client.rpc.trackRpcCallSites=true on the JVM command line and you will get a stack trace with this warning.
[WARN] 11:14:07+0100 [rpc-client-observation-pool-1] internal.RPCClientProxyHandler.onRemoval - A hot observable returned from an RPC was never subscribed to. This wastes server-side resources because it was queueing observations for retrieval. It is being closed now, but please adjust your code to call .notUsed() on the observable to close it explicitly. (Java users: subscribe to it then unsubscribe). If you aren't sure where the leak is coming from, set -Dnet.corda.client.rpc.trackRpcCallSites=true on the JVM command line and you will get a stack trace with this warning.
[WARN] 11:14:07+0100 [rpc-client-observation-pool-1] internal.RPCClientProxyHandler.onRemoval - A hot observable returned from an RPC was never subscribed to. This wastes server-side resources because it was queueing observations for retrieval. It is being closed now, but please adjust your code to call .notUsed() on the observable to close it explicitly. (Java users: subscribe to it then unsubscribe). If you aren't sure where the leak is coming from, set -Dnet.corda.client.rpc.trackRpcCallSites=true on the JVM command line and you will get a stack trace with this warning.
You will have to add key of bankAccountState.verifier to command.
In your initiator flow change command from:
val command = Command(BankAccountContract.Add(), listOf(ourIdentity.owningKey))
to:
val command = Command(BankAccountContract.Add(), listOf(ourIdentity.owningKey,bankAccountState.verifier.owningKey))

Unit Testing Spring MVC Controller that returns PagedResources

I am building an application with Spring Boot 1.4.1, Spring Data Jpa and Spring Data Test.
I have the following controller with which I want to return paged accounts:
#RequestMapping(method=RequestMethod.GET)
public HttpEntity<PagedResources<Account>> getAccounts(
Pageable pageable,
PagedResourcesAssembler assembler,
#RequestParam(value="name", required = false) String name,
#RequestParam(value="username", required = false) String username,
#RequestParam(value="email", required = false) String email,
#RequestParam(value="lastName", required = false) String lastName,
#RequestParam(value="size", required = true, defaultValue = "10") Integer size,
#RequestParam(value="page", required = true, defaultValue = "0") int page,
#RequestParam(value="sort", required = false, defaultValue = "username") String sort,
#RequestParam(value="direction", required = false, defaultValue = "asc") String direction,
UriComponentsBuilder uriBuilder,
HttpServletRequest request,
HttpServletResponse response) {
// form page request
AccountList list = null;
Page<Account> resultPage = null;
Direction sortDirection = Direction.ASC;
if(direction.equals("desc")) {
sortDirection = Direction.DESC;
}
PageRequest pReq = new PageRequest(page, size, sortDirection, sort);
resultPage = accountService.findAll(pReq);
return new ResponseEntity<>(assembler.toResource(resultPage), HttpStatus.OK);
}
My test method is:
#Test
public void getAccountsTest() throws Exception {
String uri = uriBase + "/accounts";
List<Account> list = new ArrayList<Account>();
list.add(accountOne);
list.add(accountTwo);
Page<Account> returnPage = new PageImpl<Account>(list, new PageRequest(0,10), list.size());
when(accountService.findAll(any(PageRequest.class))).thenReturn(returnPage);
mockMvc.perform(get(uri))
.andExpect(status().isOk())
.andDo(print())
.andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.accounts", hasSize(2)))
.andExpect(jsonPath("$.accounts[*].username",
hasItems(endsWith(accountOne.getUsername()), endsWith(accountTwo.getUsername()))))
.andExpect(jsonPath("$.accounts[*].email",
hasItems(endsWith(accountOne.getEmail()), endsWith(accountTwo.getEmail()))));
}
My problem is, that when I run the JUnit test it breaks with the error
org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.domain.Pageable]: Specified class is an interface
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:99)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:142)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:80)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:102)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155)
at de.campuz.platform.rest.controller.AccountControllerTestDoc.getAccountsTest(AccountControllerTestDoc.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.restdocs.JUnitRestDocumentation$1.evaluate(JUnitRestDocumentation.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
I added the #EnableSpringDataWebSupport annotation to my web config but the error still persists. When running the application as is the controller works just fine, I'll get the paged accounts as the JSON response. But I can't figure out how I can test my Controllers.
Does anyone have an idea how to fix this specific problem or how to unit test Spring MVC controllers which return paged content in general?
I solved it by removing the Pageable pageable from the Controller constructor, because I didn't need it anyway. Then the PagedResourcesAssembler assembler threw the error
org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.data.web.PagedResourcesAssembler]:
No default constructor found; nested exception is java.lang.NoSuchMethodException:
org.springframework.data.web.PagedResourcesAssembler.<init>()
I digged a bit into the topic of the ResourceAssembler and came up with the following solution:
Controller:
#RequestMapping(method=RequestMethod.GET)
public ResponseEntity<PagedResources<AccountResource>> getAccounts(
#RequestParam(value="name", required = false) String name,
#RequestParam(value="username", required = false) String username,
#RequestParam(value="email", required = false) String email,
#RequestParam(value="lastName", required = false) String lastName,
#RequestParam(value="size", required = true, defaultValue = "10") Integer size,
#RequestParam(value="page", required = true, defaultValue = "0") int page,
#RequestParam(value="sort", required = false, defaultValue = "username") String sort,
#RequestParam(value="direction", required = false, defaultValue = "asc") String direction,
UriComponentsBuilder uriBuilder,
HttpServletRequest request,
HttpServletResponse response) {
// Build page request
AccountList list = null;
Page<Account> resultPage = null;
Direction sortDirection = Direction.ASC;
if(direction.equals("desc")) {
sortDirection = Direction.DESC;
}
PageRequest pReq = new PageRequest(page, size, sortDirection, sort);
resultPage = accountService.findAll(pReq);
HateoasPageableHandlerMethodArgumentResolver resolver = new HateoasPageableHandlerMethodArgumentResolver();
PagedResourcesAssembler<Account> accountPageAssembler = new PagedResourcesAssembler<Account>(resolver, null);
return new ResponseEntity<PagedResources<AccountResource>>(accountPageAssembler.toResource(resultPage, new AccountResourceAsm()), HttpStatus.OK);
}
Where I create the Resource Assembler with the HateoasPageableHandlerMethodArgumentResolver to transform the Page to the PagedResource I wanted to return.
Then I could finally run the controller test (as seen in the question) successfully.
This answer helped me a lot, thanks Oliver Gierke and Patrick Cornelissen.
Having the same problem, I wanted to avoid "manually" fetching the PagedResourcesAssembler in the controller.
Adding this to the test class fixed it for me :
#Import(HateoasAwareSpringDataWebConfiguration.class)

Sequence contains no elements error when reading metadata

I am using Kentor Auth Services and trying to get it to work with Thinktecture Identity Server. I am getting this error when reading the metadata:
Sequence contains no elements
Here is the code that I am using in the Startup.cs file:
var authServicesOptions = new Kentor.AuthServices.Owin.KentorAuthServicesAuthenticationOptions(false)
{
SPOptions = new SPOptions
{
EntityId = new EntityId("https://dev.identity.research.ufl.edu:4432/AuthServices")
},
SignInAsAuthenticationType = signInAsType,
AuthenticationType = "saml2p",
Caption = "SAML2p",
};
authServicesOptions.IdentityProviders.Add(new IdentityProvider(
new EntityId("urn:edu:ufl:dev:00856"),
authServicesOptions.SPOptions)
{
MetadataLocation = "https://dev.identity.research.ufl.edu:4432/EMvc/Metadata.txt",
});
app.UseKentorAuthServicesAuthentication(authServicesOptions);
Also I'm including the error message and part of the stack trace below.
Thanks very much for any help you can provide in how I should troubleshoot this error.
Sincerely,
Cheryl Bearden
[InvalidOperationException: Sequence contains no elements]
System.Linq.Enumerable.Single(IEnumerable1 source) +310
Kentor.AuthServices.IdentityProvider.ReadMetadataIdpDescriptor(ExtendedEntityDescriptor metadata) +108
Kentor.AuthServices.IdentityProvider.ReadMetadata(ExtendedEntityDescriptor metadata) +132
Kentor.AuthServices.IdentityProvider.DoLoadMetadata() +127
Kentor.AuthServices.IdentityProvider.ReloadMetadataIfRequired() +169
Kentor.AuthServices.IdentityProvider.CreateAuthenticateRequest(AuthServicesUrls authServicesUrls) +73
Kentor.AuthServices.WebSso.SignInCommand.InitiateLoginToIdp(IOptions options, IDictionary2 relayData, AuthServicesUrls urls, IdentityProvider idp, Uri returnUrl) +36
Kentor.AuthServices.WebSso.SignInCommand.Run(EntityId idpEntityId, String returnPath, HttpRequestData request, IOptions options, IDictionary`2 relayData) +447
Kentor.AuthServices.Owin.d__1.MoveNext() +781

FacebookConnectionFactory connection GET request for "https://graph.facebook.com/me" resulted in 400 (Bad Request) MissingAuthorizationException:

I am trying to develop an app for Facebook. I wrote a facebook controller and created connectionFactory object, got the oAuth oprations and accessgrant object. I got the access token also But Once I try to create a connection
Connection<Facebook> connection = connectionFactory.createConnection(accessGrant);
I am getting the error :
MissingAuthorizationException: Authorization is required for the operation, but the API binding was created without authorization.
Full stack trace :
[1/25/12 9:18:17:097 IST] 0000001a SystemOut O oauthOperations :org.springframework.social.facebook.connect.FacebookOAuth2Template#46714671
[1/25/12 9:18:17:097 IST] 0000001a SystemOut O authorizeUrl :https://graph.facebook.com/oauth/authorize?client_id=xxxxx&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A80%2FSpringSocial%2Fstart&scope=read_stream%2Cemail%2Cpublish_stream%2Coffline_access
[1/25/12 9:19:15:930 IST] 0000001a SystemOut O oauthOperations authorizationCode :org.springframework.social.facebook.connect.FacebookOAuth2Template#46714671
[1/25/12 9:19:25:197 IST] 0000001a SystemOut O accssTokentemp :xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[1/25/12 9:19:35:541 IST] 0000001a SystemOut O facebook :org.springframework.social.facebook.api.impl.FacebookTemplate#21c221c2
[1/25/12 9:19:35:994 IST] 0000001a RestTemplate W org.springframework.web.client.RestTemplate handleResponseError GET request for "https://graph.facebook.com/me" resulted in 400 (Bad Request); invoking error handler
[1/25/12 9:19:36:041 IST] 0000001a servlet E com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0068E: Uncaught exception created in one of the service methods of the servlet SpringSocial in application SpringSocialFacebookEar. Exception created : org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.social.MissingAuthorizationException: Authorization is required for the operation, but the API binding was created without authorization.
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:574)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:718)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
at com.ibm.ws.cache.servlet.ServletWrapper.serviceProxied(ServletWrapper.java:307)
at com.ibm.ws.cache.servlet.CacheHook.handleFragment(CacheHook.java:579)
at com.ibm.ws.cache.servlet.CacheHook.handleServlet(CacheHook.java:250)
at com.ibm.ws.cache.servlet.ServletWrapper.service(ServletWrapper.java:259)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1663)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:939)
Caused by: org.springframework.social.MissingAuthorizationException: Authorization is required for the operation, but the API binding was created without authorization.
at org.springframework.social.facebook.api.impl.FacebookErrorHandler.handleFacebookError(FacebookErrorHandler.java:95)
at org.springframework.social.facebook.api.impl.FacebookErrorHandler.handleError(FacebookErrorHandler.java:60)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:486)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:443)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:415)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:213)
at org.springframework.social.facebook.api.impl.FacebookTemplate.fetchObject(FacebookTemplate.java:165)
at org.springframework.social.facebook.api.impl.UserTemplate.getUserProfile(UserTemplate.java:50)
at org.springframework.social.facebook.api.impl.UserTemplate.getUserProfile(UserTemplate.java:46)
at org.springframework.social.facebook.connect.FacebookAdapter.setConnectionValues(FacebookAdapter.java:42)
at org.springframework.social.facebook.connect.FacebookAdapter.setConnectionValues(FacebookAdapter.java:30)
at org.springframework.social.connect.support.AbstractConnection.setValues(AbstractConnection.java:172)
at org.springframework.social.connect.support.AbstractConnection.initKey(AbstractConnection.java:135)
at org.springframework.social.connect.support.OAuth2Connection.(OAuth2Connection.java:73)
at org.springframework.social.connect.support.OAuth2ConnectionFactory.createConnection(OAuth2ConnectionFactory.java:58)
at com.tgt.social.controller.FaceBookConnectController.facebookConnect(FaceBookConnectController.java:107)
My Controller class :
#Controller
public class FaceBookConnectController {
private static OAuth2Operations oauthOperations = null;
private static FacebookConnectionFactory connectionFactory = null;
private static OAuth2Parameters params = null;
#RequestMapping("/start")
public ModelAndView facebookConnect(Model model,HttpServletRequest request,HttpServletResponse response) {
Security.setProperty("ssl.SocketFactory.provider", "com.ibm.jsse2.SSLSocketFactoryImpl");
Security.setProperty("ssl.ServerSocketFactory.provider", "com.ibm.jsse2.SSLServerSocketFactoryImpl");
System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", "8888");
String clientId = "xxxxxxxxx";
String clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
String redirectUrl = "http://localhost:80/SpringSocial/start";
try {
String authorizationCode = request.getParameter("code");
if(null != authorizationCode){
MultiValueMap paramsMap1 = new LinkedMultiValueMap();
System.out.println("oauthOperations authorizationCode :"+oauthOperations);
//paramsMap.set("client_id", clientId);
//paramsMap.set("client_secret", clientSecret);
//paramsMap.set("code", authorizationCode);
paramsMap1.set("redirect_uri", redirectUrl);
paramsMap1.set("grant_type", "authorization_code");
paramsMap1.set("scope","read_stream,user_about_me,user_birthday,user_likes,user_status,email,publish_stream,offline_access");
//AccessGrant accessGrant = oauthOperations.exchangeForAccess(authorizationCode, redirectUrl, paramsMap1);
System.out.println("connectionFactory authorizationCode :"+connectionFactory);
AccessGrant accessGrant = connectionFactory.getOAuthOperations().exchangeForAccess(authorizationCode, redirectUrl, paramsMap1);
String accssTokentemp = accessGrant.getAccessToken();
System.out.println("accssTokentemp :"+accssTokentemp);
String scope_p = accessGrant.getScope();
System.out.println("scope_p :"+scope_p);
Facebook facebook = new FacebookTemplate(accssTokentemp);
System.out.println("facebook :"+facebook);
Connection<Facebook> connection = connectionFactory.createConnection(accessGrant);
//FacebookProfile userProfile = facebook.userOperations().getUserProfile();
System.out.println("connection :"+connection);
}else{
MultiValueMap paramsMap = new LinkedMultiValueMap();
connectionFactory = new FacebookConnectionFactory(clientId,clientSecret);
System.out.println("connectionFactory :"+connectionFactory);
oauthOperations = connectionFactory.getOAuthOperations();
params = new OAuth2Parameters();
params.setRedirectUri(redirectUrl);
params.setScope("read_stream,user_about_me,user_birthday,user_likes,user_status,email,publish_stream,offline_access");
paramsMap.set("client_id", clientId);
paramsMap.set("client_secret", clientSecret);
paramsMap.set("code", authorizationCode);
paramsMap.set("redirect_uri", redirectUrl);
paramsMap.set("grant_type", "authorization_code");
System.out.println("oauthOperations :"+oauthOperations);
String authorizeUrl = oauthOperations.buildAuthorizeUrl(GrantType.AUTHORIZATION_CODE, params);
System.out.println("authorizeUrl :"+authorizeUrl);
response.sendRedirect(authorizeUrl);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Please let me know what is wrong here?
Is the instantiation is not correct for connectionFactory object.
You need to addConnection to the usersConnectionRepository since social tries to locate a user's already established connection if any, and tries to get it authorized and use it

Resources