I'm working in a Grails application that uses a remote Rice 2.3.6 (embedded in Kuali Coeus 5.2.1) as an IAM backend. Many aspects of this are successful! But this one is not:
org.kuali.rice.kim.api.role.RoleService kimRoleServiceClient
...
kimRoleServiceClient.assignPrincipalToRole(
principalId,
role.namespace,
role.name,
qualifiers)
kimRoleServiceClient.principalHasRole(
principalId,
[kimRoleServiceClient.getRoleIdByNamespaceCodeAndName(
role.namespace,
role.name)],
qualifiers) // returns true, as expected
kimRoleServiceClient.removePrincipalFromRole(
principalId,
role.namespace,
role.name,
qualifiers)
kimRoleServiceClient.principalHasRole(
principalId,
[kimRoleServiceClient.getRoleIdByNamespaceCodeAndName(
role.namespace,
role.name)],
qualifiers) // returns true (unexpected behavior)
No error is returned, either as a result of the call or as an exception logged in the remote KC catalina.out. I can verify in the KC UI that the role is still assigned, and it's not a caching issue between the two calls -- I can wait a respectable amount of time and the role is still assigned.
Any clues?
EDIT:
It was suggested on the rice.collab mailing list that the problem may be related to KULRICE-9835: removePrincipalFromRole uses attribute id instead of attribute name in qualifier, which is marked as fixed in Rice 2.5.1. This might present a further hurdle, but at the moment this call fails even for roles with no qualifier, i.e. when qualifiers in the call above is an empty Map.
Your edit comments that you are not passing qualifiers however the code throws an exception in this case looking at the code ? Could this be your issue ?
./rice-middleware/kim/kim-impl/src/main/java/org/kuali/rice/kim/impl/role/RoleServiceImpl.java
#Override
public void removePrincipalFromRole(String principalId, String namespaceCode, String roleName,
Map<String, String> qualifier) throws RiceIllegalArgumentException {
if (StringUtils.isBlank(principalId)) {
throw new RiceIllegalArgumentException("principalId is null");
}
if (StringUtils.isBlank(namespaceCode)) {
throw new RiceIllegalArgumentException("namespaceCode is null");
}
if (StringUtils.isBlank(roleName)) {
throw new RiceIllegalArgumentException("roleName is null");
}
if (qualifier == null) {
throw new RiceIllegalArgumentException("qualifier is null");
}...
Related
I've faced with behavior that I can't understand. This issue happens when Split with AggregationStrategy is executed and during one of the iterations, an exception occurs. An exception occurs inside of Splitter in another route (direct endpoint which is called for each iteration). Seems like route execution stops just after Splitter.
Here is sample code.
This is a route that builds one report per each client and collects names of files for internal statistics.
#Component
#RequiredArgsConstructor
#FieldDefaults(level = PRIVATE, makeFinal = true)
public class ReportRouteBuilder extends RouteBuilder {
ClientRepository clientRepository;
#Override
public void configure() throws Exception {
errorHandler(deadLetterChannel("direct:handleError")); //handles an error, adds error message to internal error collector for statistic and writes log
from("direct:generateReports")
.setProperty("reportTask", body()) //at this point there is in the body an object of type ReportTask, containig all data required for building report
.bean(clientRepository, "getAllClients") // Body is a List<Client>
.split(body())
.aggregationStrategy(new FileNamesListAggregationStrategy())
.to("direct:generateReportForClient") // creates report which is saved in the file system. uses the same error handler
.end()
//when an exception occurs during split then code after splitter is not executed
.log("Finished generating reports. Files created ${body}"); // Body has to be List<String> with file names.
}
}
AggregationStrategy is pretty simple - it just extracts the name of the file. If the header is absent it returns NULL.
public class FileNamesListAggregationStrategy extends AbstractListAggregationStrategy<String> {
#Override
public String getValue(Exchange exchange) {
Message inMessage = exchange.getIn();
return inMessage.getHeader(Exchange.FILE_NAME, String.class);
}
}
When everything goes smoothly after splitting there is in the Body List with all file names. But when in the route "direct:generateReportForClient" some exception occurred (I've added error simulation for one client) than aggregated body just contains one less file name -it's OK (everything was aggregated correctly).
BUT just after Split after route execution stops and result that is in the body at this point (List with file names) is returned to the client (FluentProducer) which expects ReportTask as a response body.
and it tries to convert value - List (aggregated result) to ReportTask and it causes org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type
Why route breaks after split? All errors were handled and aggregation finished correctly.
PS I've read Camel In Action book and Documentation about Splitter but I haven't found the answer.
PPS project runs on Spring Boot 2.3.1 and Camel 3.3.0
UPDATE
This route is started by FluentProducerTemplate
ReportTask processedReportTask = producer.to("direct:generateReports")
.withBody(reportTask)
.request(ReportTask.class);
The problem is error handler + custom aggregation strategy in the split.
From Camel in Action book (5.3.5):
WARNING When using a custom AggregationStrategy with the Splitter,
it’s important to know that you’re responsible for handling
exceptions. If you don’t propagate the exception back, the Splitter
will assume you’ve handled the exception and will ignore it.
In your code, you use the aggregation strategy extended from AbstractListAggregationStrategy. Let's look to aggregate method in AbstractListAggregationStrategy:
#Override
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
List<V> list;
if (oldExchange == null) {
list = getList(newExchange);
} else {
list = getList(oldExchange);
}
if (newExchange != null) {
V value = getValue(newExchange);
if (value != null) {
list.add(value);
}
}
return oldExchange != null ? oldExchange : newExchange;
}
If a first exchange is handled by error handler we will have in result exchange (newExchange) number of properties set by Error Handler (Exchange.EXCEPTION_CAUGHT, Exchange.FAILURE_ENDPOINT, Exchange.ERRORHANDLER_HANDLED and Exchange.FAILURE_HANDLED) and exchange.errorHandlerHandled=true. Methods getErrorHandlerHandled()/setErrorHandlerHandled(Boolean errorHandlerHandled) are available in ExtendedExchange interface.
In this case, your split finishes with an exchange with errorHandlerHandled=true and it breaks the route.
The reason is described in camel exception clause manual
If handled is true, then the thrown exception will be handled and
Camel will not continue routing in the original route, but break out.
To prevent this behaviour you can cast your exchange to ExtendedExchange and set errorHandlerHandled=false in the aggregation strategy aggregate method. And your route won't be broken but will be continued.
#Override
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
Exchange aggregatedExchange = super.aggregate(oldExchange, newExchange);
((ExtendedExchange) aggregatedExchange).setErrorHandlerHandled(false);
return aggregatedExchange;
}
The tricky situation is that if you have exchange handled by Error Handler as not a first one in your aggregation strategy you won't face any issue. Because camel will use the first exchange(without errorHandlerHandled=true) as a base for aggregation.
Following the changes posted here, the getNetworkType method is deprecated from Android R and onwards.
When trying to use this method in a R compiled application, results in the following exception being thrown:
java.lang.SecurityException: getDataNetworkTypeForSubscriber: uid 10225 does not have android.permission.READ_PHONE_STATE.
at android.os.Parcel.createExceptionOrNull(Parcel.java:2285)
at android.os.Parcel.createException(Parcel.java:2269)
at android.os.Parcel.readException(Parcel.java:2252)
at android.os.Parcel.readException(Parcel.java:2194)
at com.android.internal.telephony.ITelephony$Stub$Proxy.getNetworkTypeForSubscriber(ITelephony.java:7565)
at android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:2964)
at android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:2928)
at com.ironsource.environment.ConnectivityService.getCellularNetworkType(ConnectivityService.java:197)
at com.ironsource.sdk.service.DeviceData.updateWithConnectionInfo(DeviceData.java:98)
at com.ironsource.sdk.service.DeviceData.fetchMutableData(DeviceData.java:54)
at com.ironsource.sdk.service.TokenService.collectDataFromDevice(TokenService.java:120)
at com.ironsource.sdk.service.TokenService.getRawToken(TokenService.java:177)
at com.ironsource.sdk.service.TokenService.getToken(TokenService.java:166)
at com.ironsource.sdk.IronSourceNetwork.getToken(IronSourceNetwork.java:183)
This is fine and is expected according to the documentation. If I compile the application to any version before Android R, the exception doesn't show.
This exception indicates that I need to request the android.permission.READ_PHONE_STATE permission.
I wanted to know if there is a way to get the network type with any other API that does NOT require this permission (as this permission's level is dangerous and I would rather not ask the user for it).
Take runtime permission for READ_PHONE_STATE to ignore crash of getDataNetworkTypeForSubscriber
#Override
protected void onStart() {
super.onStart();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
int res = checkSelfPermission(android.Manifest.permission.READ_PHONE_STATE);
if (res != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{android.Manifest.permission.READ_PHONE_STATE}, 123);
}
}
}
private final static int REQUEST_CODE_ASK_PERMISSIONS = 1002;
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_PERMISSIONS:
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "READ_PHONE_STATE Denied", Toast.LENGTH_SHORT)
.show();
} else {
}
stepAfterSplash();
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
You can still use getDataNetworkType(); This method does not necessarily need READ_PHONE_STATE, as stated in his Doc, but that it's sufficient "that the calling app has carrier privileges".
https://developer.android.com/reference/android/telephony/TelephonyManager#getDataNetworkType()
For what I know about getting those privigileges, it could be tricky/really hard, you may look into getting carrier privileges and using this method, which is also the suggested substitution for getNetworkType().
This method necessarily need READ_PHONE_STATE by this way in your activity not just manifest >>>
// Check if the READ_PHONE_STATE permission is already available.
if(ActivityCompat.checkSelfPermission(this,Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_PHONE_STATE)) {
//here >> use getNetworkType() method
// like this example
mStationInfo.set_networkType(mTelephonyManager.getNetworkType());
}
else {}
We can use ConnectivityManager#getNetworkCapabilities and NetworkCapablities#hasTransport like this
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkCapabilities caps = cm.getNetworkCapabilities(cm.getActivityNetwork());
boolean isMobile = caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
boolean isWifi = caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
Reference:
android.net.NetworkInfo
This class was deprecated in API level 29. Callers should instead use the ConnectivityManager.NetworkCallback API
to learn about connectivity changes, or switch to use
ConnectivityManager#getNetworkCapabilities or
ConnectivityManager#getLinkProperties to get information
synchronously. Keep in mind that while callbacks are guaranteed to be
called for every event in order, synchronous calls have no such
constraints, and as such it is unadvisable to use the synchronous
methods inside the callbacks as they will often not offer a view of
networking that is consistent (that is: they may return a past or a
future state with respect to the event being processed by the
callback). Instead, callers are advised to only use the arguments of
the callbacks, possibly memorizing the specific bits of information
they need to keep from one callback to another.
So my friend I have the same trouble as you but so far I came with a temporary fix I use the compileSdkVersion 29 not 30 as well as the targetSdkVersion 29 and my buildToolsVersion 28.0.3 and my app is loading fine.
Since this problem by me its coming due a third party library so till the fix the error I can not fix it alone, but I think with this temporary solution for now is quite well.
I Have Aspect around Methods in Transactional service.
Unfortunately, when I catch errors by service, another exception is throwed. How can I prevent from this error ?
*I searched for similar question but no-one solutions seems be adequat for my case
#Aspect
#Component
public class ServiceGuard {
#Pointcut("execution(* simgenealogy.service.*.*(..))")
public void persistence() {}
#Around("persistence()")
public Object logPersistence(ProceedingJoinPoint joinPoint) {
try {
Object o = joinPoint.proceed();
return o;
} catch (ConstraintViolationException constraintException) {
// (...)
return null;
} catch (Throwable throwable) {
// (...)
return null;
}
}
}
And error log.
2019-07-29 02:10:37.979 ERROR 11300 --- [ion Thread] s.a.g.s.w.ServiceGuard :
Constraint violation: First Name cannot be empty
2019-07-29 02:10:38.023 ERROR 11300 --- [ion Thread] s.a.g.s.w.ServiceGuard :
Constraint violation: Last Name cannot by empty
Exception in thread "JavaFX Application Thread" org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:534)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:305)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at
You catch exceptions which probably occur for a reason. Then you just return null as the result of the previously executed (via proceed()) method, probably in situations where another, non-null return value is expected.
As you do not provide any application code, this is speculative, but I assume that the null return value is then assigned to a data property which ought have a non-null value (see the constraint violations in your log). More precisely you set first and last names to null which causes constraint violations which in turn causes your transaction to be rolled back because mandatory data fields are not set.
How to fix this? Either return non-null default values for first/last name (sounds strange, though) or let the original exceptions escalate instead of swallowing them and causing follow-up problems.
Bottom line: Your exception handling is just broken and needs fixing.
Ok I found solution.
#Transactional is also #Arround Aspect. The problem was in ordering aspects. My Guard class wasn't in fact around Transaction. Put #Order(0) on Guard and #Order(1) on #Transactional service solved issue.
When user clicks the link this method takes the user id and other data and writes it to the database. I can't seem to find a way to track what is the user id since the id is automatically generated.
I am using membership base separately from my base. In order to find userID I was trying to compare UserName strings. I get this error: "An unhandled exception was generated during the execution of the current web request." Also "Cannot create an abstract class."
Is there a better way to compare two strings form the two databases? Or is there a better way? This is my first time using lambda expressions.
I tried using Single() and First() instead of Where(), but I still get the same error.
[HttpPost]
public ActionResult AddToList(Review review, int id, HttpContextBase context)
{
try
{
if (ModelState.IsValid)
{
//User user = new User();
//user.UserID = db.Users.Where(c => c.UserName == context.User.Identity.Name);
User user = new User();
Movie movie = db.Movies.Find(id);
review.MovieID = movie.MovieID;
string username = context.User.Identity.Name;
user = (User)db.Users.Where(p => p.UserName.Equals(username));
review.UserID = user.UserID;
db.Reviews.Add(review);
db.SaveChanges();
return RedirectToAction("Index");
};
}
catch (DataException)
{
//Log the error (add a variable name after DataException)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
return View(review);
}
you're problem is likely this line:
user = (User)db.Users.Where(p => p.UserName.Equals(username));
the Where() extension method returns an IEnumerable, not a single instance, so your implicit cast will fail every time. what you're looking for is either First() or FirstOrDefault(). First() will throw an exception if there is no match though, while FirstOrDefault()will return a null if no match is found. the line should be :
user = db.Users.First(p => p.UserName.Equals(username));
you probably have bigger problems than that, but this is the cause of your current error.
EDIT
upon further looking at your code, you're asking for a HttpContextBase in your action result call. you never use it, and it's probably the cause of the Cannot create an abstract class exception. remove that parameter and see if you get any different results.
I realise that similar questions have been asked before however none of the solutions provided worked.
Examining the token returned from the BeginGetResponse method I see that the following exception is thrown there:
'token.AsyncWaitHandle' threw an exception of type 'System.NotSupportedException'
This page tells me that this exception means the Callback parameter is Nothing, however I'm passing the callback - and the debugger breaks into the callback method when I insert a breakpoint. However the request object in the callback is always null. I can view the same exception detail in the result object in the callback method.
I've tried using new AsyncCallback(ProcessResponse) when calling BeginGetResponse
I've tried adding request.AllowReadStreamBuffering = true;
I've tried this in-emulator and on-device, with no luck on either.
public static void GetQuakes(int numDays)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://magma.geonet.org.nz/services/quake/geojson/quake?numberDays=" + numDays);
// Examining this token reveals the exception.
var token = request.BeginGetResponse(ProcessResponse, request);
}
static void ProcessResponse(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
if (request != null)
{
// do stuff...
}
}
So I'm at a bit of a loss as to where to look next.
'token.AsyncWaitHandle' threw an exception of type
'System.NotSupportedException'
This page tells me that this exception means the Callback parameter is
Nothing
The documentation you are looking at http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse%28v=vs.95%29.aspx is for BeginGetResponse. Silverlight does not use the AsyncWaitHandle, and correctly throws a NotSupportedException. You are seeing the exception System.NotSupportedException is for call to IAsyncResult.AsyncWaitHandle you are making when you inspect token.
The documentation on IAsyncResult.AsyncWaitHandle says explicitly that it is up to the implementation of IAsyncResult whether they create a wait handle http://msdn.microsoft.com/en-us/library/system.iasyncresult.asyncwaithandle(v=vs.95).aspx. Worrying about this is sending you down th wrong path.
I think you need to descibe the actual problem you are seeing. It is great to know what you have investigated, but in this case it does help resolve the problem.
The code should work and in ProcessResponse request should not be null when you test it in the if statement. I just copied the code you have provided into a windows phone application and ran it with no problems.